MVC3, Models, Create & Edit Hidden Fields - asp.net-mvc-3

I have a few models in my MVC3 web app that have fields that need to be set "behind the scenes" when a user creates or edits an object/entity.
I'm trying to figure out what the best practice is regarding these types of fields.
For example...
public class EntityA {
public int Id { get; set; }
public string Title { get; set; }
...
[ForeignKey("User")]
public int UpdatedBy_Id { get; set; }
public virtual User UpdatedBy { get; set; }
}
The create and edit views for this allow the user to edit the "Title" field, but the "UpdatedBy" field needs to be set by the app when the entity is inserted or updated.
Is it best to drop a hidden field on the views and set "UpdatedBy_Id" there, or use the model property "get/set" body to do so? ...or... Should this be on the HttpPost in the controller?

This is where DTOs (Data Transfer Objects) come in handy.
Your view uses a DTO as it's model. The DTO mirrors your entity object in terms of properties, but excludes properties which you don't want the user to be able to manipulate.
Then in your controller when you are ready to persist the Entity, you create a new Entity object, and take the properties from the DTO passed to the action and copy them to your Entity object. It is at this point you can set the UpdatedBy property.
To make life easier when mapping properties from the Entity to the DTO (and vice versa), you can look at AutoMapper, which will handle this automatically, if you use the same names for your properties.
If you just pass the Entity to the view, there is the potential for the user to change the values of properties that you don't want them to be able to.

I'd prefer to place fields like this outside of user control. Especially if they're integer fields a user can edit to make phony records. The choices then fall between using TempData(if session is enabled) or possibly retrieving it on the fly for the current user. If you're not worried about the user modifying them, then I'd go with a simple hidden field or placing it in the route values for the post, allowing the framework to do the work for you.

I'd say use a hidden field and set the UpdatedBy_Id. It will then be posted back with the form and it can be databound like the rest of the information.

Related

asp.net core Identity user customization

Detail
I am developing web application in asp.net core with Identity. now in my application I have two kind of user. Customer and Partner both have different profile information and login scenario.customer can login from simple signup from web page but partner can signup from different view with different mandatory fields.
Problem
How can I design Schema.
what are the good practices in this case.
What are the drawback.
Code
This is what I have done so far
public class ApplicationUser : IdentityUser
{
public CustomerProfile CustomerProfile { get; set; }
}
Use inheritance:
public class ApplicationUser : IdentityUser {}
public class Customer : ApplicationUser
{
// Customer-specific properties
}
public class Partner : ApplicationUser
{
// Partner-specific properties
}
By default, this will be implemented via STI (single-table inheritance). That means you'll have just your standard AspNetUsers table containing columns for the properties on ApplicationUser and all derived types. A discriminator column will be added to indicate which type was actually saved, which will then be used to instantiate the right type when queried.
For the most part, this works just fine. The one downside is that properties on derived classes must be nullable. The reason is simple: it would be impossible to provide values for Customer columns while saving a Partner and vice versa. However, the properties only need be nullable at the database-level. You can still require that they be set in forms and such via a view model.
The alternative is to use TPT (table-per-type). With this approach, you'll get AspNetUsers, but also Customers and Partners tables as well. However, the tables for the derived types will have columns corresponding only to the properties specific to that type and a foreign key back to AspNetUsers. All common properties are stored there. With this, you can now enforce columns have values at the database-level, but querying users will require a join. To use TPT, you simply add the Table attribute to your class, i.e. [Table("Customers")] and [Table("Partners")], respectively.
The one important thing to keep in mind with using inheritance, though, is that you need to work with the type you actually want to be persisted. If you save an ApplicationUser instance, it will be an ApplicationUser, not a Customer or Partner. In this regard, you need to be careful with using the correct types with things like UserManager which generically reference the user type. Even if you create an instance of Customer, if you save it via an instance of UserManager<ApplicationUser>, it will upcast to ApplicationUser and that is what will be persisted. To create a new Customer, you'll need an instance of UserManager<Customer>. Likewise, for partners.
However, this also works to your benefit, as if you attempt to look up a user from an instance of UserManager<Customer> for example, you will only find them if they are in fact a Customer. In this way, it makes it trivially simple to have separate portals where only one or the other can log in, as you've indicated that you want.

Multiple/separate entries for single field during form submission

I have a form on my ASP MVC3 website that needs to allow for multiple entries for one of it's fields prior to the form being submitted. It is for a sales agent's information, however since we outsource our sales staff one agent could have multiple companies they work with.
This form used to be provided by an Access database. The company information was input using the form below, which was built into the main form:
This would allow the user to select from DSS Company designation and input the company (or Agency Stat) Id, hit the forward arrow, and input the next until finished. The user also had the ability for cycle back and forth through their entries prior to submitting the form.
Does anyone know of any specific Ajax or JQuery plugins or techniques that I could use to implement this on an ASP MVC3 page?
You may consider using a variable length list which would allow you to dynamically add/remove records to a view model collection.
Your view model might look like this:
public class CompanyViewModel
{
public int SelectedCompanyId { get; set; }
public IEnumerable<selectListItem> Companies { get; set; }
public string AgencyStat { get; set; }
}
and then of course your view will be strongly typed to an IEnumerable<CompanyViewModel>. You would have add/remove links that would allow the user to add or remove records to this list and finally when he decides to submit the form your HttpPost controller action will receive the collection for further processing.

How to prevent user from modifying some fields on the form?

I am using MVC3 and EF4 to write a web application. I am using an action header like below to capture the form values submitted by the user.
<HttpPost()>
Public Function Edit(ByVal prod as Product) As ActionResult
I use the below code for updating the record.
db.Attach(prod)
db.ObjectStateManager.ChangeObjectState(prod, EntityState.Modified)
db.SaveChanges()
I get the submitted values in prod object which I update in the database. The problem is that there are some users who are not allowed to modify certain fields in a Product, say ProductCost. I have disabled the textboxes for such fields in the HTML. But since it is clientside, the user can easily enable it using some tool like Firebug and modify the value.
The only solution I could come up was to retrieve the existing record from the database and copy its ProductCost value into prod.ProductCost. But I don't like firing a query for achieving this. Is there a better way to achieve this?
Edit: I found the below link to update particular fields. How to update only one field using Entity Framework?
You can use the below code to modify a particular field.
context.ObjectStateManager.GetObjectStateEntry(user).SetModifiedProperty("FieldName");
Now the question is do I have to write the above statement for every field the user is able to modify? If yes, suppose the Product model has 10 fields (1 primary key) and the user is allowed to modify all of them except the primary key, I need to write 9 statements?? Is there a method where you can specify multiple properties at once. Or even better something where you specify the properties which are not modified. (Note: I know I can run a loop over an array of field names to avoid writing 9 statements. I am asking for an alternative method and not refactoring the above)
Never trust client data. Always have your server code to validate the input and do appropriate actions.
I would create separate overloads of my Respiratory method update the product in different ways and then check what is the current user's access type, If he is admin, i will call the overload which updates everything, if he is a manager, i will call the method which updates name,imageUrl and price and if he is an employee, i will call the method which updates only name and ImageURL
[HttpPost]
public ActionResult Edit(Product prod)
{
if(ModelState.IsValid)
{
string userType=GetCurrentUserTypeFromSomeWhere();
if(userType=="admin")
{
repo.UpdateProduct(prod);
}
else if(userType=="manager")
{
repo.UpdateProduct(prod.ID, prod.Name, prod.ImageUrl, prod.Price);
}
else if(userType=="employee")
{
repo.UpdateProduct(prod.ID, prod.Name, prod.ImageUrl);
}
return RedirectToAction("Updated",new {id=prod.ID});
}
}

ASP.NET MVC3 , Why we need strongly-typed View?

I have read Scott Guthrie's Blog - ASP.NET MVC 3: New #model keyword in Razor
One things i don't realizes is a page will binding value in different ways,but why we have to enforce the view binding from Model?
For example, a user control panel of forum website, it may have the user information, the post history, the user setting etc.
From the view of data model, the binding source can be come from different table : users, posts, user_settings etc.
However, one view only can reference one #model directive.
Actually ,i can add what properties to model that i have to use.
So what is the advantage of make the view became strongly-typed?
However, one view only can reference one #model directive.
Yes, and this should be your view model. A view model is a class that you specifically design to meet the requirements of a given view. And you do this for each view
From the view of data model, the binding source can be come from
different table : users, posts, user_settings etc.
Great, then design a view model that will contain all the necessary properties and have the controller build this view model aggregating the information from the different places and pass it to the view for displaying.
You should never pass your domain models to your views. Because views are normally the projection of one or more domain models => thus the need to define a view model.
1) You can use automatic scaffolding
2) IntelliSense support
3) Compile time type checking
Your view model should be decoupled from your business models.
A single page will have a single view model.
For example:
public class UserPost
{
public string UserName { get; set; }
public string Subject { get; set; }
public IEnumerable<Message> Messages { get; set; }
}
Your UserName property will be coming from the Users table and the UserName field in it.
Your Subject might be coming from a Subjects table and the Messages from another one.
Your view should be concerned only with presenting already processed information, and not querying data sources.
Therefore it is best practice to create a ViewModel per View. This ViewModel contains all properties needed by the view (users, post, settings etc).
In the controller/model you can instantiate the ViewModel and fill its properties. So don't supply a single table/list of records to a view, but a ViewModel.
The advantage is that, with everything strongly typed, there's less chance on runtime errors. Further, when something changes (i.e. database columns), these errors will be detected by the IDE directly.

Updating object and relations with Entity Framework Code First and ASP.Net MVC

I'm using Entity Framework Code First and whilst I have working code, I'm having to make what are strictly unnecessary database calls in order to process the following update.
I have a simple POCO class for an album with a collection of related tags:
public class Album
{
public int Id { get; set; }
public string Title { get; set; }
public decimal Price { get; set; }
public virtual IList<Tag> Tags { get; private set; }
}
public class Tag
{
public int Id { get; set; }
public string Name { get; set; }
}
This is updated via an MVC form - with the tags represented by a series of check-boxes.
So when I get to my Update method in the respository, I have an album class populated with a list of tags - with in theory all I need to make the update.
However the only way I could find to get the list of tags to update (to delete any that were previously set but are now unchecked, and to add any that are currently checked) was to retrieve the original Album from the context and update it.
And secondly because in my implementation the Name field of the Tag is marked with [Required], and that in my Album object populated from the form I only have the IDs of the tags, I also have to retrieve each tag before updating.
Here's my code:
public void Update(Album album)
{
var albumToUpdate = GetById(album.Id); // - need to retrieve album with tags in order to update tags
albumToUpdate.Title = album.Title;
albumToUpdate.Price = album.Price;
albumToUpdate.Tags.Clear();
if (album.Tags != null)
{
foreach (var tag in album.Tags)
{
var tagToAdd = context.Tags.Find(tag.Id); // - need to retrieve full details of tag so doesn't fail validation
albumToUpdate.AddTag(tagToAdd);
}
}
}
Appreciate any thoughts as to how I could accomodate this with fewer database hits. It's not a major deal for this particular function (part of a site admin tool) but would like to know I'm doing things the best way.
Your approach - reloading the entity graph from the database and merge the changes manually into it - is correct in my opinion and the best you can do.
Forget for a moment that you use Entity Framework. What would you do if you had to write SQL statements manually? (EF is a wrapper around a SQL statement generator.) You get posted back an object graph - an Album with a list of Tags. How would you decide now which tags you have to write an INSERT, which tags a DELETE and which tags an UPDATE statement for? (I assume that your relationship between Album and Tag is many-to-many, so you write into a join table.) If you don't know the original state in the database you can't decide. Does the tag relation exist in the database or not? You have to query the database to find the answer, no matter if you use EF or direct SQL.
I see only two alternatives:
Track the entity changes yourself. For you MVC web application it would mean that you have to store the original state with the former GET request somewhere, for example in a session state or in hidden input fields in the page. With the POST request you can retrieve then the original state, build and attach the orginal graph and merge changes into it.
Write a Stored Procedure which takes the album and tag collection and let the SP do the work to create the appropriate SQL statements.
The first way is complicated and has its costs in HTTP payload (hidden input fields) or is depending on a fragile session state. And the second conflicts with why you are using an ORM. Unless you have really serious performance problems or are a SQL master I would not consider a Stored Procedure.
Firstly, I think that this pattern of updates is wrong somehow in that instead of passing in an Album which I assume is a replica or partial replica of the one you want to update (same ID at least), why don't you load the actual one first and apply your changes to it?
If you cannot do that, it might be less confusing to not pass in the same entity (Album) but instead use a data transfer object (DTO) or other message with just the fields you need and then apply that to the loaded Album.
As to the main problem of how to avoid loading each tag, EF should do that for you, but I don't know that it does. For example, NHibernate will not load a lazy entity if you are only setting a relationship because you have not touched any properties of Tag, so it only needs the Id to use it. Hopefully, EF does the same but maybe not (I'm assuming you've profiled it).
If EF does not behave like that you could try two things: firstly, so long as there is no cascade update on Tag, use a skeleton one with just the ID (that is, create the object yourself and just set the Id); this won't work if EF cascade updates the Tag. Secondly, you could implement your own cache for Tags and get them from memory.

Resources