MVC, Updating a Model, Razor - asp.net-mvc

I have a view, model and a controller, I want the user to start editing the page of a new contact.
They will
Enter the First and Last Name
Click Save
The Controller commits the save.
Expand the page to Show display name for editing.
In forms Asp.net I stick the Primary Key of the Saved record in the view state so on the next save, I do an update vs. an Insert.
How do I do that in MVC, Razor? I have seen examples using a Hidden Field but I would think there is a better way. I would prefer it not shown at all, or at least encrypted but I do not want to build the encryption or decryption routines.

User HiddenFor() method of Html helper class. #Html.HiddenFor(model => model.Id). By the way, ViewState is stored in a hidden field in ASP.NET.
If you are really wanting to encrypt the data like in viewState, you can use Html.Serialize()method which serializes and encrypts entire model in view and you will then have to De-serialize it in the controller after it's posted. Have a look at this article

Related

Why are my dotnet 5.0 mvc form fields retaining their input values on post?

I have an dot net 5.0 mvc page which takes a model object (ClassFoo) which when constructed generates an instance of (classBar). ClassBar has various properties (FieldA, FieldB, FieldC) all are strings.
The Views content is all in a form and the form's input fields are all from ClassFoo.ClassBar's various properties. Initially, when the page is accessed, all form input values are empty. However when I put data into them and then submit the form, the form values are still there when the page loads. However I don't understand why this is because I'm explicitly creating a new model during the controller operation but I am not actually populating the Model.ClassBar with the content from the post before I return model to the View for generation.
What I would expect is that all of the form fields would be empty however that is not the case. I know if asp.net the form values are stored and restored automatically but I didn't think that happened in mvc.
After looking into ModelState recommended by Nick Albrech in the comments I reviewed the hint associated w/ the HtmlHelper.TextBoxFor() which states the following:
... Adds a "value" attribute to the element containing the first non-null value found in: the ActionContext.ModelState entry with full name, or the expression evaluated against ViewDataDictionary.Model. See [IHtmlHelper.NameFor] for more information about a "full name".
So effectively what's happening is similar to what I thought asp.net mvc wasn't doing in that it populates the ModelState from a get/post request with the name and values of the form being submitted. Then based on the use of these helper functions (and also asp-for attributes used in razor views views), it either provides values from the saved model state form values OR the model passed to the view. Note: this does not seem to work if you set the value of an input element = #Model.[someProperty]
The take away from this is that you do not necessarily need to update your model object with content from the previous form submit in order to have the page populate the form contents back to the screen. Allow asp.net mvc to do the manual tasks by making use of these razor helpers.
Shoutout to Nick for the assist on this one. A solid member of the stackOverflow community.

How to handle hidden fields in MVC forms?

I have a FormViewModel that handles different fields. Many of them have not to be presented to the user (such as modified_date, current_user_id) so I am using hidden fields to respect the FormViewModel structure. When submitted they are passed to the controller's action and correctly saved to the DB but I'm asking: is it the best way to do in ASPNET MVC? I would have preferred to define them in FormViewModel and using only the fields to be modified instead of showing also the non-modifiable as hidden fields.
Is there a better way to do it?
If these fields are not being touched by the user than I would do this;
Create a FormViewModel with only the fields that are relevant. Also the primary key.
The primary key still needs to be on the page me thinks.
Then in the controller you accept the FormViewModel as the argument, you then load the actual model and update, validate fields as required and save the model.
The above is simplistic and you'll have more layers but you should get the idea
I think you can do a few things to make your life a little easier:
Let the URL (and the routing mechanism) give you the id (the primary key of whatever you are trying to edit)
You can have a URL like '/Student/Edit/1' Routing will ensure that your Action method gets the id value directly.
Have 2 action methods to handle your request. One decorated with [HttpGet] to render the initial form to the user (where you just retrieve your object from the repository and pass it on to your View) and a [HttpPost] one to actually handle the post back from the user.
The second method could look something like:
[HttpPost]
[ActionName("Edit")]
public ActionResult EditPost(int id) {
...your code here...
}
Retrieve the actual record from the repository/store based on the id passed in.
Use the UpdateModel function to apply the changes to the database record and pass on the record back to your repository layer to store it back in the database.
However, in a real world application, you will probably want separation of concerns and decoupling between your repository and your view layer (ASP.NET MVC.)
If they are part of the model, the method you are using is perfectly fine. You even have a helper method in HtmlHelper.HiddenFor to output the hidden field for you. However, if the values are something like modified date or current user, you'd might be better suited passing those along from your controller to a DTO for your data layer. I'm making some assumptions about what you're doing for data access, though.
The risk with storing data which shouldn't be modified in hidden fields is that it can be modified using a browsers built in/extension developer tools. Upon post these changes will be saved to your database (if that's how you're handling the action).
To protect hidden fields you can use the MVC Security Extensions project https://mvcsecurity.codeplex.com.
Say the field you want to protect is Id...
On you controller post method add:
[ValidateAntiModelInjection("Id")]
Within your view add:
#Html.AntiModelInjectionFor(m => m.Id)
#Html.HiddenFor(m => m.Id)
On post your Id field will be validated.
Create a FormViewModel with only the fields that are relevant. Also the primary key.
The primary key still needs to be on the page me thinks.
Then in the controller you accept the FormViewModel as the argument, you then load the actual model and update, validate fields as required and save the model.
The above is simplistic and you'll have more layers but you should get the idea

asp.net mvc how to save?

I have the following model:
Customer:
ID
Name
Address
Phone
Fax
I added an Edit view based on the above model from the controller. I modified the Edit view to only allow edit on the Phone and Fax field (deleted the rest). When I submit it I get an error. It works if I leave the Edit view untouched (5 fields). However I only want to allow change in the last 2 fields.
I am lost, please help. Thanks :)
If you are using the MVC ability to populate your entity/class i.e. your action sig looks like this:
ViewResult MyAction(MyObject object) {
...
Save(MyObject);
}
then you'll need to make sure you include the other field, non-editable, either as visible information or using Html.Hidden within the form scope to ensure you have a fully populated object. Remember, the web is stateless and the server has no idea which record you were editing unless it has the keys to do so retrospectively.
The other option would be to retrieve the original object (for which you'll still need the primary key) from the database, update the fields from your form data and then submit the changes. We'd need to know the specific error to be able to help further, the code you are using would also be a great help.
Without knowing more I would guess it has something to do with binding null to a non null property in your model. Can you give me more details on the model, the error.
If you are using the default mvc model binder then it will only bind the fields you submit. So either submit as hidden or dont use a model binder and manually map the variable from Request.Form into a copy of the model you pulled form the db.

asp.net image in a form and HTTPPost

HI,
I'm sure I'm missing something very obvious here so please forgive me.
I'm using MVC 2 Beta and I have a model that has several properties, strings, ints etc. the usual stuff.
It also has a byte array that contains an image.
I have an edit action method on my controller decorated with a [HTTPGet] attribute.
The method passes the model to the view which is a form that has the usual text boxes that bind to the various string properties and an img element that is bound to the byte array/image.
This all works as it should and I see all the data including the image. This is all pretty standard stuff.
But when the user submits the form to my [HTTPPost] version of the action method that accepts the same model as its parameter the image property is null. i.e. the image property does not appear to be part of the model binding.
In the normal course of events we would do some validation and pass the model back to the view to be rendered so the user can see if the edits were successfull or not. But just passing the model back "as is" - the view does not render the image again because its no longer in the model.
I know I can go and get the image again (from the database or where ever) and put it back in the model before passing it to the view, but is that the right stratergy or have I missed something?
Regards,
Simon
How do you render the image that is contained as binary data in model? Do you use classic webforms controls (what would be not recomded in mvc terminology)?
Anyway, if the image is only displayed in the view it is not posted when the user submits the form because only input fields (checkboxes, text fields, hiddens) are submited to the server. image element is not. Remember that in MVC it is simple HTML doing all the work of posting data to the server - there is no viewstate nor automatical postback that will persist the state of the controls.
You have two solutions:
Encode binary data in some hidden field so it would be posted again.
(better) Do not send the image data back and forth between the client and the server, but detect if the user provided new image (i expect you wolud use file input for that) and if the user left the file input empty then update the model with the image already stored in database to display it again. Otherwise update the image in the database.
Anyway, i'm curious how do you display image from binary data in model. I think it would be simpler to create some controller action that would return binary data so you could use URL of that action in src attribute of img tag, or store images as files and use their URL instead of binary data.

Naming of ASP.NET controls inside User Controls with ASP.NET MVC

I am wondering if there is a way to make ASP.NET controls play nicely with my ASP.NET MVC app. Here is what I am doing.
I have an order page which displays info about a single Order object. The page will normally have a bunch of rows of data, each row representing an OrderItem object. Each row is an ASP.NET User Control. On the user control there is a form element with two text boxes (Quantity and Price), and an update button.
When I click the update button, I expect the form to post the data for that individual OrderItem row to a controller method and update the OrderItem record in the database.
Here is my problem: When the post happens, the framework complains because the fields on the form don't match the parameters on the controller method. Each form field is something like "OrderItem_1$Quantity" or "OrderItem_2$Price" instead of just "Quantity" or "Price" which would match my method parameters.
I have been told that I can overcome this by making sure that the IDs of all my controls are unique for the page, but allow the NAMEs to be repeated between different forms, so that if a form for an individual row is posted, the name can be something that will match what is on my controller method.
The only problem is that I am using ASP.NET controls for my text boxes (which I REALLY want to continue doing) and I can't find any way to override the name field. There is no Name propery on an ASP.NET control, and even when I try to set it using the Attributes accessor property by saying "control.Attributes["Name"] = "Price";" it just adds another name= attribute to the HTML tag which doesn't work.
Does any one know how I can make this work? I really don't like all of the HtmlHelper functions like TextBox and DropDown because I hate having my .aspx be so PHP or ASP like with the <%%> tags and everything. Thanks!
I think you're straddled between two worlds of ASP.NET WebForms and ASP.NET MVC. You really need to use the Html.TextBox methods, etc. in MVC. This gives you complete control over the markup, which is one of the main benefits of MVC.
The very problem you're having with control over the generated HTML, e.g. getting two name attributes, is exactly what MVC is designed to address. If you stop fighting it and go with the flow, it'll work much better.
<% %> tags aren't a problem unless you have logic in there. Putting simple presentation logic on your view is fine.
If you don't like this, then maybe it's better to stick with standard ASP.NET.

Resources