Why does my model not get saved by the view?
I开发者_开发问答've been making some very basic MVC views to save some data. To date I've based them all on LinqToSql classes; now for the first time I've based a form on a simple little class I've created on my own, called a Purchase
.
public class Purchase {
long UserID;
decimal Amount;
string Description;
}
Created a view that looks like this:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<TestViewer.Models.Purchase>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Test Purchase
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>
Test Purchase</h2>
<% using (Html.BeginForm("SavePurchase", "Home")) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.UserID) %>
</div>
<div class="editor-field">
<%: Html.DropDownListFor(model => model.UserID,
SystemUser.Select(u=>new SelectListItem{ Text=u.UserName, Value=u.ID.ToString()}).OrderBy(s=>s.Text))%>
<%: Html.ValidationMessageFor(model => model.UserID) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.Amount) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Amount) %>
<%: Html.ValidationMessageFor(model => model.Amount) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.Description) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Description) %>
<%: Html.ValidationMessageFor(model => model.Description) %>
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% } %>
<div>
<%: Html.ActionLink("Back to List", "Index") %>
</div>
</asp:Content>
But when I get back into my code in HomeController
:
public ActionResult SavePurchase(Purchase p) {
// code here
}
the object p
has default values (zeroes and blanks) for all its field values.
Why? What did I do wrong?
In your Purchase
class use properties instead of fields (for better encapsulation) and most importantly they need to have public setters for this to work:
public class Purchase
{
public long UserID { get; set; }
public decimal Amount { get; set; }
public string Description { get; set; }
}
In your example you are using fields, but those fields are internal so you cannot expect the default model binder being able to set them any values and they just get their default values inside your POST action.
This being said the fact that those properties are not being said is the smallest problem you have with this code. In your case the worst thing is that you are using your Linq2Sql models inside your views and that's one of the worst anti-patterns I see people doing in ASP.NET MVC applications. You absolutely should be using view models. That's what views should be passed from controllers and that's what controllers should get from views.
精彩评论