Model binding in MVC3 application passing null to action parameter under Mono - asp.net

A simple controller action that is posted to which takes a model used by the view's form isn't being bound to the form fields when running under Mono 2.10.1. Under MS.NET the same code executes as expected with the model populated with the corresponding form values.
The controller action is defined as:
[HttpPost]
public ActionResult Login(LoginModel login, string returnUrl)
{
The first parameter login is null when the form is submitted on Mono, and fully populated with the login form fields under MS.NET.
The form fields are accessible via the Request.Form collection (ie Request.Form["UserName"]) under Mono, so it seems to just be the binding that isn't working.
This used to be an MVC2 app - anyone experienced something similar?

I tracked this down to a custom data annotations model validation provider that we register to handle our own way of localizing error messages such as Required and Display Name on model properties.
Commenting out the following line:
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(LocalizedRequiredAttribute), typeof(RequiredAttributeAdapter));
From global asax fixes the issue, and the custom model validator still works - looks like it was a hang over from MVC2 days.

Related

SpringMVC get Model from previous call

My setup is pretty simple.
I have a Controller with a get- and a postmethod. The getmethod fills a Model which is then used to render a thymeleaftemplate of an HTML-form.
When the User clicks submit the formdata will be posted to the postmethod. This method then performes some businesslogic which may have two outcomes.
First possibilty: Everything works well and a redirect to the getmethod is performed.
Second Possibility: An exception occurs. In that case the user shall be presented with the same form he submitted containing the data he tried to submit. So in that case my postmethod returns the identifying String of the same template as the getmethod. But thymeleaf tells me that the model is lacking some attributes.
Why doesn't spring inject the same model in the postmethod that has been used to render the template of the getmethod.
Is there any way, to recycle the model from the getcall in the postmethod?
I usually redirect after a post method by using the RedirectAttributes. It is used to add data to the model even in a redirect.
This is an example of how to use it:
#PostMapping("/course")
public String addCourse(#RequestParam("course") Course course, RedirectAttributes redirectAttributes) {
// show a popup that the `account.name` has been added
redirectAttrs
.addAttribute("course", course)
.addFlashAttribute("message", "Course created!");
return "redirect:/courseOverview";
}

ASP.NET MVC 4 - how to use a viewmodel when editing & persisting data

mvc 4 using sql server 2008, code first, ef5
I have a ViewModel associated with a view.
As a starting point I'm modifying the scaffolding created by VS.
I can populate the form fine.
When the user clicks save - this is the code in the scaffolding:
[HttpPost]
public ActionResult Edit(Place place)
{
if (ModelState.IsValid)
{
db.Entry(place).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(place);
Place is a model. I need to pass a viewmodel (including place) back to this.
How do I persist the viewmodel in the database using EF? Do I have to split it into models first?
When I try that I get this error:
Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.
When I debug it also seems the PlaceID (from model) is missing from the model that's passed back to the controller httpPost Edit controller - maybe that's the source of the error?
Are there any examples of best practice online for this - I can't find anything.
Thanks.
How do I persist the viewmodel in the database using EF?
You do not persist view models in a database. They role is not to be persisted. View models are used to define the logic used by your view. It is inside your controller action that you could map the view model back to your domain model that will be persisted using the data access technology of your choice. You could use AutoMapper to map between your view models and domain models.
When I debug it also seems the PlaceID (from model) is missing from
the model that's passed back to the controller httpPost Edit
controller - maybe that's the source of the error?
Yes, that's the possible reason. If you want to update some record in the database EF need to know which is this record using the ID.
This was missing in the View:
#Html.HiddenFor(model => model.place.PlaceID)
This keeps tabs on the ID of the model

Spring MVC: Session attribute required - not found in session

I am receiving the following error on submitting my form:
org.springframework.web.HttpSessionRequiredException: Session attribute 'rulesForm' required - not found in session
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.raiseSessionRequiredException(AnnotationMethodHandlerAdapter.java:722)
My JSP contains the following:
<form:form id="rulesForm" modelAttribute="rulesForm" action="save.do">
...
</form>
My Controller contains the following:
#Controller
#RequestMapping("/rules")
#SessionAttributes({"rulesForm", "deskForm"})
public class RulesController {
.
.
.
#RequestMapping(value = "/save.do")
public ModelAndView saveRuleAttributesAndRules(#Valid
#ModelAttribute("rulesForm")
RulesFormDTO rulesForm, BindingResult bindingResult, HttpSession session, Principal principal) {
It seems that if I leave my browser open for a while with my form displaying and then I attempt to perform a submit after some time I get this error.
Really what I want to happen in this case is for the new "rulesForm" object to be created...how can I achieve this?
Thanks
As the Javadoc on #SessionAttribute indicates use of the annotation means you want store the specified model attributes in the session, which means you need to add them to the model first. Spring MVC will not create them.
In other words when you add a #ModelAttribute("rulesForm") controller method argument you're telling Spring MVC to look for it in the model or create a new instance if not found. However if you also add #SessionAttributes, Spring MVC will not attempt to create a new instance and will expect the object to be either in the model or in the session. You can use a #ModelAttribute method to add your object initially.

Asp.net mvc 2 model binders what's behind scene

Im starting with MVC2 and i have a simple question:
If i have a typed view with a form inside, and this textbox created with lambda expressions:
<%: Html.TextBoxFor(e => e.Name)%>
When i submit this form the default model binder take the request form, takes the model typed to the view, serialize the data posted (as a this model) and pass it to an action of my controller.
To try to explain myself better, lets imagine that i have a url like localhost/edittestmodel/ID/1 and i have in my controller action the following code:
public ActionResult Edit(int id)
{
TestModel testmodel=new TestModel();
testmodel.Name="texttorenderintotextbox";
//whats the class that place the testmodel properties into the view?
return View(testmodel);
}
What's the responsable class for place the Name property of my testmodel object into the textbox
<%: Html.TextBoxFor(e => e.Name)%>
Thanks in advance.
Best Regards.
Jose.
It's the TextBoxFor helper method that's responsible for generating the input field from the lambda expression.
View's don't have anything to do in POST request and model binding
When you have strong type views, model type is barely used to have the simplicity of code intellisense in view's code (so you can use lambda expressions like in your example).
But when you POST data back, nothing gets checked against the view. It gets checked against controller action parameters though. And if there's a parameter with a certain custom model binder type, that particular model binder is used to process incoming data.
But to answer your question: TextBoxFor checks your strong type view's model and generates particular textbox with correct name attribute. So data from it will be posted back under the correct form field name.
To go even deeper. It's the view engine that parses view's ASPX code and runs all server side scripts including Html.TextBoxFor() call.

ASP.NET MVC model binding and action parameters

Let's say I have a controller action defined as:
public ActionResult(MyModel model, string someParameter)
{
// do stuff
}
I have a custom model binder for the MyModel type, and there is a form field called "SomeParameter" in the view that is not bound to the model. How does ASP.NET MVC know to pass the value of Request.Form["SomeParameter"] as the value for the "someParameter" argument to the action?
ASP.NET uses reflection to determine the correct method to invoke and to built up the parameters to pass. It does so based on the FormCollection array. Basically it will see model.* Keysin there and a FormCollection["someParameter"] it will first try Action(model,someParameter) then Action(model) and then Action(). Since it finds an Action with a model and someParameter arguments it will then try to convert them into the arguments types.
However by default it does so blindly which introduces some security risks, this blog post goes into greater detail on this.
If anyone can post up a link which in greater detail describes how ModelBinding is done under the hood that would be great.
Because the default model binder will be used for someParameter unless you specify otherwise. And the default model binder does exactly what you describe.
Phil Haack has a post on How a Method becomes an Action which explains just how this resolution happens.
Sounds like you need a model binder. These allow you to define how form data is bound to a model parameter. You can read more about them at the following:
ASP.NET MVC Preview 5 and Form Posting Scenarios
How to use the ASP.NET MVC Modelbinder
One of the easiest way is having Html items on the page with same name as the input parameters in the action method.
EX) In the View we have:
<input name="refNo" type="text">
Then in the Action method:
public ActionResult getOrders(string refNo)
So, it simply bind the value of "refNo" to the input parameter of the "getOrders" action.

Resources