ASP.NET MVC Form Overflow

I have a controller with two actions:

[AcceptVerbs("GET")] public ActionResult Add() { PrepareViewDataForAddAction(); return View(); } [AcceptVerbs("POST")] public ActionResult Add([GigBinderAttribute]Gig gig, FormCollection formCollection) { if (ViewData.ModelState.IsValid) { GigManager.Save(gig); return RedirectToAction("Index", gig.ID); } PrepareViewDataForAddAction(); return View(gig); } 

As you can see, when the form publishes its data, the Add action uses GigBinder (IModelBinder implementation)

In this binder, I:

  if (int.TryParse(bindingContext.HttpContext.Request.Form["StartDate.Hour"], out hour)) { gig.StartDate.Hour = hour; } else { bindingContext.ModelState.AddModelError("Doors", "You need to tell us when the doors open"); } 

The form contains a text field with the identifier "StartDate.Hour".

As you can see above, GigBinder checks that the user types an integer into the text field with the identifier "StartDate.Hour". If not, the modelstate model is added using AddModelError.

Since the gigss.StartDate.Hour property is strongly typed, I cannot set its value, for example, "TEST", if the user entered this into the text field of the form.

Therefore, I cannot set the value of gigs.StartDate.Hour, since the user entered a string, not an integer.

Since the "Add Action" action returns a view and passes the model (return View (gig);), if the state of the model is invalid when the form is re-displayed using the mssages check, the "TEST" value is not displayed in the text box. Instead, it will be the value by default is gig.StartDate.Hour.

How do I get around this problem? I'm really stuck!

+6
asp.net-mvc forms
source share
3 answers

I think the problem is that your ViewModel is not coming close enough to your view. In MVC, it is very important that your ViewModel matches your view as closely as possible.

In your ViewModel, you accept an integer, but in your view, you use a TextBox to render the property, which allows you to use any text. Here the inconsistency and the difficulties with which you are trying to match them are a symptom of the inconsistency.

I think you need:
1. Change the type of the ViewModel property to a string, and then run a check in your controller to verify that the string entered is actually a number or:
2. Change the control that appears in the view for the control that only allows you to enter a number using a user control or Javascript check (as recommended by @Qun Wang).

Personally, I would recommend option 1. Thus, the ViewModel is independent of the implementation of the View.

+2
source share

Could you do this in the PrepareViewDataForAddAction method? ..

 if (!ViewData.ModelState.IsValid) { ViewData["StartDate.Hour"] = "Error"; } 

Other fields in the form will continue to be populated based on the properties of the Gig object.

+1
source share

I think you need to do a basic client side check first. do not let it send messages to the server.

+1
source share

All Articles