ASP.NEt storing data - asp.net-4.0

I have a scenario where i want : To create a data class which will hold data for every element on my web form within a property. eg:
public class UserData
{
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public bool Gender { get; set; }
}
Afterwards, on click of submit button initialize the object of this data class and assign values to respective properties as given below:
UserData userData = new UserData();
userData.FirstName = txtFirstName.Text; // (Always name the controls with prefixes i.e. txt for TextBox, ddl from DropDownList etc.)
userData.MiddleName = txtMiddleName.Text;
userData.FirstName = txtLastName.Text;
userData.Gender = rdbMale.Checked ? "Male" : "Female";
When user will enter a data in a form and click the button, entered data should be displayed on the page. But this should happen every time and on second click of button both the records should display on a page. Means after entering five records, all five should display on page.
I don't know where to store the data.
Can anyone help me

You can store the data in a cookie and read the cookie on submit button click.
But again there are some limitations w.r.t size, user disabling it etc.
Response.Cookies["userName"].Value = txtbox.text;

Related

ASP.NET Core 6 Write value to Page without iteration?

I am trying to write a specific value to a page in ASP.NET Core 6. I found multiple solutions with iterators but I am not able to write a single value from non-iteratable models / instances (no enumerators & lists) to a page.
public class UserViewModel
{
public string Id { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
}
This models purpose is to get filled with values from the Identity Framework.
public UserViewModel umodel { get; set; }
Said model gets instanced, filled without any problems - it holds values (checked via console) in page.cshtml.cs:
var user = await _userManager.FindByIdAsync(id);
UserViewModel UserModel = new UserViewModel();
UserModel.UserName = user.UserName;
UserModel.Email = user.Email;
UserModel.Id = user.Id;
Console.WriteLine(UserModel.UserName);
Console.WriteLine(UserModel.Id);
Console.WriteLine(UserModel.Email);
If I try to access it on the corresponding page (page.cshtml) I can only access its name without any problems:
#Html.DisplayNameFor(model => model.umodel.Email)
When I want to access its content there is no value on the page.
#Html.DisplayFor(model => model.umodel.Email)
How can I access the values in this model on a razor page? All the solutions I found based on some kind of iterator and therefore models that had some kind of enumerator or where instanced and filled as a list.
From the code you posted, you aren't populating the page's UserViewModel property. You instantiated a different UserViewModel instance. You wrote the values of that to the Console, but the actual model property (umodel) has not been populated.
Try this in the OnGet method:
var user = await _userManager.FindByIdAsync(id);
umodel.UserName = user.UserName;
umodel.Email = user.Email;
umodel.Id = user.Id;
When rendering property values, you don't need the DisplayFor helper (unless you are using display templates). You just need to prefix the property with #:
#Model.umodel.UserName
I figured it out. There hast to be an instance of the model / class but in a specific way and naming. See following example:
Model:
public class IdentityUserModel
{
public string Id { get; set; }
public string ?UserName { get; set; }
public string ?Email { get; set; }
}
Reference to model in the Main class of the Page (page.cshtml.cs):
public IdentityUserModel IUserModel { get; set; }
Then the important part in the OnGet/OnGetAsync function(?) (page.cshtml.cs):
IUserModel = new(); // <-- instance
var user = [whatever...]
IUserModel.UserName = user.UserName;
IUserModel.Email = user.Email;
IUserModel.Id = user.Id;
Then to write on the page.cshtml:
#Model.IUserModel.Id
My understanding is that there has to be an instance of the class in die page context with exactly the same name (therefore = new() without instance name). I may have been blind but reading throug microsofts learn pages again this is was not clear at all to me.
Thanks to Mike Brind for sending me in the right direction with his input.

String array in query parameters swagger

I'm working on a project where there is an endpoint that receives a list of strings in the parameter, as shown in the code below:
public class PaymentFilter
{
public List<string> Status {get; set; }
}
[HttpGet]
public IActionResult Get([FromQuery] PaymentFilter filter)
{
...
}
However, in the swagger interface the status list is not reflected, as shown in the image:
How do I enable entries for the status list?
Click Try it out button and click Add string item then you can add
parameter

DropDownListFor Composite Key with Value Column

I'm building a Roles/Permissions component for my application. My Role view model looks like this:
public class RoleView
{
public int Id { get; set; }
public ApplicationWithPermissionsView Application { get; set; }
public List<RolePermissionView> Permissions { get; set; }
public IEnumerable<KeyValuePair<string, int>> PermissionValues
{
get
{
return EnumHelper.ToList<PermissionValue>();
}
}
[Required]
public string Name { get; set; }
}
The RolePermission view model looks like this:
public class RolePermissionView
{
public int PermissionId { get; set; }
public int RoleId { get; set; }
public PermissionValue Value { get; set; }
}
PermissionValue is an enum that has members NotSet, Allow, Deny, and stores an int value in the database.
If I go to a role edit page, I display a list of permission categories, which each have a list of permissions, with the respective values (RolePermission) for each permission for that role. As you can see, RolePermissionView has composite keys (PermissionId, RoleId).
How can I build a drop down list, that shows a list of possible permission values and selects the correct permission value for that particular permission?
The following generates the drop down lists, but doesn't select any values. Also, doesn't give each dropdown list a unique name or ID, so binding definitely won't work. I assume if I later move this into an Editor Template they will have uniques.
#foreach (var permission in category.Permissions)
{
<tr>
<td>#permission.Description</td>
<td>#Html.DropDownListFor(m => m.Permissions.Find(p => p.PermissionId == permission.Id).PermissionValue, new SelectList(Model.PermissionValues, "Value", "Key"))</td>
</tr>
}
The trouble here is mostly syntactic. Bear in mind that for things like DropDownListFor and the other *For-style helpers, you're passing an expression, not a literal instance of something. The helper then attempts to parse that expression to create a name attribute value on the input that will (hopefully) bind when the data is posted back. Obviously, then, doing something like Find is not going to work, because there's no way to translate that so that the same thing happens on the other end after posting. Instead, you should do something like:
#for (var i = 0; i < category.Permissions.Count(); i++)
{
<tr>
<td>#category.Permissions[i].Description</td>
<td>#Html.DropDownListFor(m => category.Permissions[i].PermissionValue, Model.PermissionValues)</td>
</tr>
}
Now, the expression is concrete enough to bind to.
Also, Change your PermissionValues property to be IEnumerable<SelectListItem> instead of using KeyValuePair. Then, there's no need to manually create a SelectList, which will save you a lot of potential headaches. To construct the Value of the SelectListItem, I would simply append the two composite ids as strings (since the value must be a string anyways). Join them by some delimiter like a comma. Then, on post, you can get the posted value and split it by the same delimiter to get your two ids back. Obviously, you'll also then need to convert them both back to ints. You can only post one value back from a select, so this is really your only option when it comes to composite keys.

Gathering Active Directory Data for MVC intranet application

I need assistance with gathering Active Directory data based on a table in my DB. I have an entity class that holds user requests. Each request has the user's windows name from System.Web.HttpContext.Current.User.Identity.Name. My problem is I cannot figure out how to setup a linq query to associate the AD username to the rest of the AD so I can display their full names instead of their username in my table. Here is what I have so far, any help will be appreciated.
public partial class RequestInfo
{
public int RequestInfoId { get; set; }
public string RequestByUserADId { get; set; }
public System.DateTime RequestDateTime { get; set; }
public string Explanation { get; set; }
public virtual UserInfo UserInfo { get; set; } // where I define my custom roles
}
I can query AD by using the code below. I have tried Get Active Directory User Information With Windows Authentication in MVC 4, but it did not help.
using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
using (UserPrincipal user = UserPrincipal.FindByIdentity(context, requestByAdId))
{
return user.DisplayName
}
I may be off here because I am not sure if you are able to successful establish a user principal or not but if you have the user principal you can get property information like the following:
user.GetProperty("propertyName")
Here is a static method that should get you the department for a user, for example.
public static String GetDepartment(UserPrincipal principal)
{
return principal.GetProperty("department");
}
Let me know where this gets you and I can elaborate further if this isn't working.
Edit
It appears you need to go one level deeper to get the fields that aren't by default a part of the user principal. For this you will need to get the directory entry from the user principal first:
DirectoryEntry directoryEntry = (userPrincipal.GetUnderlyingObject() as DirectoryEntry);
Then you need to check if the attribute you are looking for exists, and if it does, get the value. A great way to do this is to create a helper method that you pass your directory entry to along with the string value for the property name that you want to get.
public string GetProperty(DirectoryEntry directoryEntry, string propertyName)
{
if (directoryEntry.Properties.Contains(propertyName))
{
return directoryEntry.Properties[propertyName][0].ToString();
}
else
{
return string.Empty;
}
}
Please note that going to the underlying object is expensive. I believe this operation, by default, is cached for you so subsequent use of this information can be retrieved from cache. Playing around with
directoryEntry.RefreshCache
will get you started with that.
Let me know if this does the trick for you!

Kendo UI Grid displays [object Object]

I have a class
public class LookupClass {
public int Id { get; set; }
public string Name { get; set; }
}
That I have referenced in another class
public class Sampleclass {
public int Id { get; set; }
public LookupClass LookupEntry { get; set; }
}
which is is displayed in a KendoUI Grid
#(Html.Kendo().Grid<SampleClass>()
.Name("SomeGrid")
.Columns(cols => {
cols.Bound(o => o.LookupEntry).Title("Lookup Column") // Displays [object Object]
cols.Bound(o => o.LookupEntry.Name) // displays name correctly
}
.DataSource(datasource =>
// leaving this out since the data is seems to be loading correctly.
)
)
When displaying the grid it just displays [object Object] for the value in the cells in the "Lookup Column" column. I have gotten the editor template working (leaving out code since not necessary, basically copied from here) and saving/loading works (left out for simplicity), but I can't seem to figure out how to display the Name property from the Lookup class.
Found a KendoUI example that shows how to do this (http://demos.kendoui.com/web/grid/editing-custom.html)
Basically you have to use a ClientTemplate to display the property you want to display
#(Html.Kendo().Grid<SampleClass>()
.Name("SomeGrid")
.Columns(cols => {
cols.Bound(o => o.LookupEntry).ClientTemplate("#=LookupEntry.Name#").Title("Lookup Column")
}
)
On a side note, if you try to create a new record, it will produce an error about not finding LookupEntry (don't remember exact message). In the example listed, there is also a bit in the model section that shows how to set a default object.