2
votes

I'm having an issue where the model is valid when it creates the HttpGet page, but invalid (some properties are null) on the HttpPost.

Here is my call to open the page:

            var quote = new Quote
            {
                Agency = assignedAgency,
                Insured = insured,
                RiskAddress = insured.Address
            };
            db.Quotes.Add(quote);
            db.SaveChanges();

            return RedirectToAction("Edit", "Quote", quote.QuoteID);  

And the HttpGet ActionResult - At this point, the model is valid. Insured and Agency properties are populated and have their respective Address properties populated as well.

    [HttpGet]
    public ActionResult Edit(int quoteID)
    {
        var model = db.Quotes.Find(quoteID);

       return View(model);
    }

And the HttpPort ActionResult - At the entry of this method, the Insured, Agency and their respective Address properties are null, causing an invalid Model state.

    [HttpPost]
    public ActionResult Edit(Quote model)
    {
        if (ModelState.IsValid)
        {
            if (model.SubCosts > 0)
            {
                model.InsuredSubs = true;
                model.SubClassCode = "95626 - Subcontractor - TEST CLASS";
                model.SubClassExposure = model.SubCosts;
            }

            db.Entry(model).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Edit", new { quoteID = model.QuoteID });
        }
        return View(model);
    }

And the HTML:

 @model DomaniOnline.Models.DomaniData.Quote

 @{
     ViewBag.Title = "Classification";
  }

  <h2>General Liability Classification</h2>

  @using (Html.BeginForm())
   {
     @Html.ValidationSummary(true)
     <fieldset>

    @Html.HiddenFor(model => model.QuoteID)
    @Html.HiddenFor(model => model.Insured)
    @Html.HiddenFor(model => model.Insured.Address)
    @Html.HiddenFor(model => model.RiskAddress)
    @Html.HiddenFor(model => model.Agency)
    @Html.HiddenFor(model => model.Agency.Address)

        .
        .
        .
        .
    <p>
        @Html.ActionLink("Back to Insured Info", "Edit", "Insured", new { insuredID = Model.Insured.InsuredID }, null)
        <input type="submit" value="Save & Continue" />
    </p>
</fieldset>
}

I'd like to point out that the "Back to Insured Info" ActionLink at the bottom of the page works just fine and is able to supply the correct model.Insured.InsuredID. But for some reason, when submitting the form to the HttpPost, any property that is of a custom datatype is null. the Html.HiddenFor<> were added as a test while trying to get this to work.

edit: Classes:

 public class Quote
 {
    public virtual int QuoteID { get; set; }
    public virtual Address RiskAddress { get; set; }
    public virtual Agency Agency { get; set; }
    public virtual Insured Insured { get; set; }

    public virtual DateTime PropEffDate { get; set; }
    public virtual bool InsuredSubs { get; set; }
    public virtual int SubCosts { get; set; }
    .
    .
    .
  }
  public class Address
  {
    [Required]
    public virtual string StreetAddress { get; set; }
    [Required]
    public virtual string City { get; set; }
    [Required]
    public virtual string State { get; set; }
    [Required]
    public virtual string ZipCode { get; set; }
  }
  public class Insured
  {
    public virtual int InsuredID { get; set; }
    [Required]
    public virtual string Name { get; set; }
    [Required]
    public virtual Address Address { get; set; }
    public virtual string DBA { get; set; }
    [Required]
    public virtual string BusinessType { get; set; }
    public virtual string Phone { get; set; }
  }
1
Please show us the classes. Also, consider using separate ViewModels; that would probably fix the problem. - SLaks

1 Answers

1
votes

Your problem is that your using HiddenFor on complex types. This only knows how to render simple types.

I would suggest either only persisting the ID's of those objects or using the Html.Serialize helper function from the MVC Futures project to serialize your account and insured objects, then deserialize them in your controller.

http://weblogs.asp.net/shijuvarghese/archive/2010/03/06/persisting-model-state-in-asp-net-mvc-using-html-serialize.aspx

Persisting the ID's should just be the InsuredID, from which you can re-get the Insured and it's address on postback. The same with Agency.