开发者

Editing/Creating a EF Object with Foreign keys

开发者 https://www.devze.com 2023-02-04 09:35 出处:网络
I am interested in the best way to deal with foreign key relationships when using ASP.NET MVC and the Entity Framework.

I am interested in the best way to deal with foreign key relationships when using ASP.NET MVC and the Entity Framework.

I am currently using a ViewModel to output a create and edit page (using a partial), but things don't work too well when I get to posting the data back.

Before I validate my model I use the posted value from the select list to look up the foreign object and assign it to my model, but when I use UpdateModel on the edit the references end up being null, I am guessing because it is not able to bind that property correctly.

How do people normally deal with this issue? Using a ViewModel to populate my dropdowns seems straigtforward enough, but I must be missing something when it comes to the edit. Do people normally create their own binder to get around this issue?

I have tried using both strong typing and the FormCollection.

ViewModel:

public class ReportViewModel
 {
    public Report Report { get; set; }
    public SelectList ReportDeliveryMethods { get; set; }
    public string ReportDeliveryMethod { get; set; }
    public SelectList ReportReceivers { get; set; }
    public string ReportReceiver { get; set; }
    public SelectList PermitTypes { get; set; }
    public string PermitType { get; set; }
}

Controller:

[HttpPost]        
public ActionResult Edit(int id, FormCollection collection)
        {
            Report report;

            try
            {
                report = repository.GetReport(id);

                // Convert ReportDeliveryMethod to Object Reference                        
                if (!string.IsNullOrEmpty(collection["ReportDeliveryMethod"]))
                {
                    int reportDeliveryMethodId = 0;
                    if (int.TryParse(collection["ReportDeliveryMethod"], out reportDeliveryMethodId))
                    {
                        report.ReportDeliveryMethod = repository.GetReportDeliveryMethod(reportDeliveryMethodId);
                    }
                }

                // Convert ReportReceiver to Object Reference              
                if (!string.IsNullOrEmpty(collection["ReportReceiver"]))
                {
                    int reportReceiverId = 0;
                    if (int.TryParse(collection["ReportReceiver"], out reportReceiverId))
                    {
                        report.ReportReceiver = repository.GetReportReceiver(reportReceiverId);
                    }
                }

                // Convert PermitType to Object Reference              
                if (!string.IsNullOrEmpty(collection["PermitType"]))
                {
                    int permitTypeId = 0;
                    if (int.TryParse(collection["PermitType"], out permitTypeId))
                    {
                        report.PermitType = repository.GetPermitType(permitTypeId);
                    }
                }

                if (ModelState.IsValid)
                {
                    UpdateModel(report);
                    repository.Save();

                    return RedirectToAction("Index");
                }
                else
                {
                    return View();
                }
            }
            catch (Exception ex)
            {
                return View();
            }
        }

Form:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<PermitLookup.Models.ReportViewModel>" %>
<% using (Html.BeginForm())
   {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
    <legend>Fields</legend>
    <div class="editor-label">
        <%: Html.LabelFor(model => model.Report.ShareName) %>
    </div>
    <div class="editor-field">
        <%: Html.TextBoxFor(model => model.Report.ShareName) %>
        <%: Html.ValidationMessageFor(model => model.Report.ShareName)%>
    </div>
    <div class="editor-label">
        <%: Html.LabelFor(model => model.Report.Description) %>
    </div>
    <div class="editor-field">
        <%: Html.TextBoxFor(model => model.Report.Description)%>
        <%: Html.ValidationMessageFor(model => model.Report.Description)%>
    </div>
    <div class="editor-label">
        <%: Html.LabelFor(model => model.Report.Frequency)%>
    </div>
    <div class="editor-field">
        <%: Html.TextBoxFor(model => model.Report.Frequency)%>
        <%: Ht开发者_开发百科ml.ValidationMessageFor(model => model.Report.Frequency)%>
    </div>
    <div class="editor-label">
        <%: Html.LabelFor(model => model.Report.SendTime)%>
    </div>
    <div class="editor-field">
        <%: Html.TextBoxFor(model => model.Report.SendTime)%>
        <%: Html.ValidationMessageFor(model => model.Report.SendTime)%>
    </div>
    <div class="editor-label">
        <%: Html.LabelFor(model => model.Report.ReportDeliveryMethod)%>
    </div>
    <div class="editor-field">
        <%=Html.DropDownListFor(model => model.ReportDeliveryMethod, Model.ReportDeliveryMethods)%>
        <%: Html.ValidationMessageFor(model => model.Report.ReportDeliveryMethod)%>
    </div>
    <div class="editor-label">
        <%: Html.LabelFor(model => model.Report.ReportReceiver)%>
    </div>
    <div class="editor-field">
        <%=Html.DropDownListFor(model => model.ReportReceiver, Model.ReportReceivers)%>
        <%: Html.ValidationMessageFor(model => model.Report.ReportReceiver)%>
    </div>
    <div class="editor-label">
        <%: Html.LabelFor(model => model.Report.PermitType)%>
    </div>
    <div class="editor-field">
        <%=Html.DropDownListFor(model => model.PermitType, Model.PermitTypes)%>
        <%: Html.ValidationMessageFor(model => model.Report.PermitType)%>
    </div>
    <p>
        <input type="submit" value="Save" />
    </p>
</fieldset>
<% } %>


Let's consider ReportDeliveryMethod. In your view model, it's a string. On your Report object, it's a ReportDeliveryMethod type. Since a string can't be implicitly cast to a ReportDeliveryMethod, UpdateModel won't bind it.

So what are your choices?

  1. Map manually, like you're doing now.
  2. Bind the ID, rather than the object reference. EF 4 supports FK associations. You could put ReportDeliveryMethodId in your view model instead of ReportDeliveryMethod.
0

精彩评论

暂无评论...
验证码 换一张
取 消