简体   繁体   中英

ASP.NET MVC one particular view model property becoming null on returning to view

In ASP.NET MVC I have a view that's a form, and I want to be able to save the form and then it returns back to the same page showing the data you entered after saving the data to the database. I'm sure I'm just doing something stupid (this is pretty new to me), but there are some properties that I want to persist and I am setting them on the view model before I return, and I have @Html.HiddenFor inside my view's form. My confusion is that of these items are retained, and some aren't. So I have the following inside my FormController (methods and names have been simplified for brevity):

    public ActionResult Index(int? p, int? c)
        {
            FormViewModel model = new FormViewModel();
            model.p = p;
            model.c = c;
            model.dateStarted = DateTime.Now;
            return View(model);
        }

   [HttpPost]
   public ActionResult Index(FormViewModel m)
        {
            Form form;
            bool shouldUpdate = false;
            if (m.formID != null) // m.formID is always null, but m.p, c, dateStarted aren't
            {
                shouldUpdate = true;
                form = getFormnWithId((int)m.formID); //gets from database
            }
            else
            {
                form = new Form(m);
            }

            if (shouldUpdate)
            {
                editForm(form);  //edit existing entry
            }
            else {
                addForm(form);  //add to database
            }
                m.formID = form.Id;  // formn.Id is valid because the form has been updated with its Id after being added to the database
                m.p = form.p;
                m.c = form.c;

                return View(m);
        }

Inside my view (cshtml) file I have @Html.HiddenFor(model=>model.formID) as well as for other properties I want to persist but aren't being set in the form directly. The formID however, is not persisting, while the other items (represented by c and p and dateStarted) are fine. If I remove the HiddenFor for those other fields, then they don't work. I click save each time, and formID is null in the post, but it's definitely set after the form has been added to the database and the value of the formID is definitely getting sent to the view. I just don't understand why it comes back null but the other properties don't.

Here's what the model looks like:

public class FormViewModel
{
     public Nullable<int> formID {get; set;}
     public Nullable<int> c { get; set; }
     public Nullable<int> p { get; set; }
     public System.DateTime dateStarted { get; set; }
     //+ other form properties
}

View:

...

<label for="submit-form" class="btn btn-default">Save</label>
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal col-md-12">
     @Html.ValidationSummary(true, "", new { @class = "text-danger" })

        <div class="form-group">
        <!-- various form fields -->
        </div>
        @Html.HiddenFor(model => model.dateStarted)
        @Html.DisplayFor(model => model.dateStarted)<br />  <!-- just to see it while testing-->
        @Html.HiddenFor(model => model.c)
        @Html.DisplayFor(model => model.c)<br />
        @Html.HiddenFor(model => model.p)
        @Html.DisplayFor(model => model.p)<br />
        @Html.HiddenFor(model => model.formID)
        @Html.DisplayFor(model => model.formID)
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" name="Command" class="btn btn-default hidden" id="submit-form" />
            </div>
        </div>

    </div>

}

Now that I see you are setting the Form.Id in the POST request, your issue is that you are not following the PRG (Post, Redirect, Get) pattern. You are returning the same view from your POST method without any type of redirect. As a result, the model binder is holding on to the previous value of Form.Id, which was null. The reason that the model binder holds on to previous values is mainly for validation purposes (if the ModelState has an error, you can return the view, the properties remain as the user entered them along with the ModelState errors collection)

To fix this, you either need to redirect to another action or issue ModelState.Clear() in your code before you return the view.

   m.formID = form.Id;  // form.Id is valid because the form has been 
   //updated with its Id after being added to the database
   m.p = form.p;
   m.c = form.c;
   ModelState.Clear();

   return View(m);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM