2

I'm using MVC3. I have a form, that on submit, returns a PartialView that updates my page. The question/issue is -- how do I show ModelState errors and keep my form values in-tact when there is an error?

It seems this question has been asked before (see my references below), but I haven't yet found a complete answer/solution, but I'm confused...

My very simple Model

public class TEST_AjaxFormViewModel
{
    [Required]
    [StringLength(10)]
    public string Name { get; set; }
}

My View looks like this:

        <% using (Ajax.BeginForm("TEST_AjaxForm", new AjaxOptions { UpdateTargetId = "formResults" }))
           {%>

            <%:Html.ValidationSummary(true, "Please correct errors:")%>

            <div class="editor-label">
                <%:Html.LabelFor(model => model.Name)%>
            </div>
            <div class="editor-field">
                <%:Html.TextBoxFor(model => model.Name)%>
                <%:Html.ValidationMessageFor(model => model.Name)%>
            </div>
            <br />

            <div class="editor-label"></div>
            <div class="editor-field">
                <button name="button" type="submit" value="Submit">
                    Submit
                </button>
            </div>
            <br />

        <% }%>

        <div id="formResults" style="border: 1px dotted red; margin: 2.0em; padding: 1.0em;">
            <p>This is where my partial view will go</p>
        </div>

And my PartialView just spits back the output:

            <div class="editor-label"></div>
            <div class="editor-field">
                <%: Model.Name %>
            </div>
            <br />

And my Controller Action method like this

    [HttpPost]
    public ActionResult TEST_AjaxForm(TEST_AjaxFormViewModel model)
    {
        if (ModelState.IsValid)
        {   
            return PartialView("TEST_AjaxFormPartialView", model);
        }
        //else
        return View(model);  // this is wrong! what should I return instead?
    }

The issue is how do I return back the View with the ModelState errors?

In the links I provided, there is talk about returning json with status codes so that the client-side can detect an error versus success condition (i.e. RenderPartialViewToString). But I don't really understand how this all gets hookedup / consumed.

e.g. If success, just display the partial view? If error, do we just refresh the page with the updated ModelState? Can someone link together the pieces and show an end-to-end example, namely the View/jquery ajax calls?

Aside: As an alternate implementation, I used something similar to this approach, and got it working, but I don't know... it just seems wrong and as I'm refreshing more of the page than I want to on a success scenario.

http://jvance.com/blog/2010/02/20/MakingAnAjaxFormWithJQueryInASPdotNETMVC.xhtml

e.g. My Controller looks like this, where my PartialViews now contain my "form" code in both Success and Error versions.

    [HttpPost]
    public ActionResult TEST_AjaxFormSingleMasterDiv(TEST_AjaxFormViewModel model)
    {
        if (ModelState.IsValid)
        {   // no model state errors
            return PartialView("TEST_AjaxFormSingleMasterDivPartialView_Success", model);
        }
        // else, error
        return PartialView("TEST_AjaxFormSingleMasterDivPartialView_Error", model);
    }

Thanks

Community
  • 1
  • 1
Raymond
  • 3,382
  • 5
  • 43
  • 67
  • no, did not solve it. I suspect this is "by design"... which makes sense, because you have to return a PartialView... so your partial view better have what you want. – Raymond Jun 07 '11 at 18:49

2 Answers2

0

You are very close. Here is how your controller should look like:

[HttpPost]
public ActionResult TEST_AjaxForm(TEST_AjaxFormViewModel model)
{
    if (ModelState.IsValid)
    {
        // perhaps do some additional actions? Save data to DB?
        return PartialView("TEST_AjaxFormPartialView", model);
    }
    //else
    return PartialView("TEST_AjaxFormPartialView", model);
}

As you can see, whether your ModelState is valid or not, you return the same view with the same model. The only difference is that if it is valid you may want to do some additional actions.

In order to display the errors you need to add a piece to the View where the errors will be shown. However, Html.ValidationSummary or Html.ValidationMessage or Html.ValidationMessageFor need to be inside of the form in order to render. Here is your View:

@model [namespace].TEST_AjaxFormViewModel

<%: Html.BeginForm() %>
<div><%: Html.ValidationSummary() %></div>
<div class="editor-label"></div>
<div class="editor-field">
    <%: Model.Name %>
</div>
<%: Html.EndForm() %>
<br />
Dmitry Efimenko
  • 10,973
  • 7
  • 62
  • 79
0

i also had this problem and solution here did the job. its very simple: the trick is to contain the form itself inside the UpdateTargetId in the AjaxOptions: http://xhalent.wordpress.com/2011/02/05/using-unobtrusive-ajax-forms-in-asp-net-mvc3/

Eitan Rousso
  • 181
  • 1
  • 5