ASP.NET MVC3:TryUpdateModel 抛出异常
我有一个接受以下模型的视图:
Inherits="System.Web.Mvc.ViewPage<MVC_WordsByME.Models.JobCreationModel>"
这会回发到以下操作:
[HttpPost]
public ActionResult Create(FormCollection formValues)
{
var job = new JobCreationModel();
if (TryUpdateModel(job))
{
_jobRepository.AddJob(job);
_jobRepository.Save();
return RedirectToAction("Index");
}
return View(job);
}
但是,回发时会引发以下异常:
无法将“System.Int32”类型的对象转换为“System.String”类型。
描述:执行当前 Web 请求期间发生未处理的异常。 请查看堆栈跟踪以获取有关错误及其在代码中的来源的更多信息。
异常详细信息:System.InvalidCastException:无法将“System.Int32”类型的对象转换为“System.String”类型。
来源错误:
Line 135: {
Line 136: var job = new JobCreationModel();
Line 137: if (TryUpdateModel(job))
Line 138: {
Line 139: _jobRepository.AddJob((Job)job);
虽然我无法在这里突出显示它,但异常发生在第 137 行。我无法进入该方法,那么如何确定导致此异常的原因呢?
另外,TryUpdateModel 不是应该让我免受任何异常的影响,只需返回 true 或 false 来反映结果吗?我不知道它可能抛出异常。
更新:这是模型(派生的和基本的):
public class JobCreationModel : Job
{
//
// Properties
public SelectList ClientsList { get; private set; }
public SelectList Languages { get; set; }
public SelectList Users { get; set; }
//
// Constructors
public JobCreationModel()
{
var userCurrent = Membership.GetUser();
SentDate = DateTime.Now;
WorkedBy = userCurrent != null ? userCurrent.UserName : string.Empty;
DeadlineDate = DateTime.Now;
ReceivedDate = DateTime.Now;
var clientRepository = new ClientRepository();
ClientsList = new SelectList(clientRepository.GetAllClients(), "ID", "OrganisationName");
var languageRepository = new LanguageRepository();
Languages = new SelectList(languageRepository.GetAllLanguages(), "ID", "Code");
var userList = Membership.GetAllUsers();
Users = new SelectList(userList.Cast<MembershipUser>().ToList(), "UserName", "UserName", userCurrent);
}
public JobCreationModel(Job job)
{
var userCurrent = Membership.GetUser();
Client = job.Client;
ClientName = job.ClientName;
DeadlineDate = job.DeadlineDate;
FixedCost = job.FixedCost;
ID = job.ID;
Invoice = job.Invoice;
JobDescription = job.JobDescription;
JobFileName = job.JobFileName;
LanguageFrom = job.LanguageFrom;
LanguageTo = job.LanguageTo;
PONumber = job.PONumber;
ReceivedDate = job.ReceivedDate;
SentDate = job.SentDate;
WordCost = job.WordCost;
WordCount = job.WordCount;
WorkedBy = job.WorkedBy;
var clientRepository = new ClientRepository();
ClientsList = new SelectList(clientRepository.GetAllClients(), "ID", "OrganisationName");
var languageRepository = new LanguageRepository();
Languages = new SelectList(languageRepository.GetAllLanguages(), "ID", "Code");
var userList = Membership.GetAllUsers();
Users = new SelectList(userList.Cast<MembershipUser>().ToList(), "UserName", "UserName", userCurrent);
}
}
基本类型是一个实体,我能想到的显示它的最好方法是显示它后面的 XML:
<EntityType Name="Jobs">
<Key>
<PropertyRef Name="ID" />
</Key>
<Property Name="ID" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
<Property Name="JobDescription" Type="nvarchar" Nullable="false" MaxLength="200" />
<Property Name="ReceivedDate" Type="datetime" Nullable="false" />
<Property Name="DeadlineDate" Type="datetime" Nullable="false" />
<Property Name="SentDate" Type="datetime" Nullable="false" />
<Property Name="Invoice" Type="int" />
<Property Name="WordCount" Type="int" Nullable="false" />
<Property Name="WordCost" Type="float" Nullable="false" />
<Property Name="FixedCost" Type="float" Nullable="false" />
<Property Name="Client" Type="int" Nullable="false" />
<Property Name="JobFileName" Type="nvarchar" Nullable="false" MaxLength="500" />
<Property Name="WorkedBy" Type="varchar" Nullable="false" MaxLength="50" />
<Property Name="PONumber" Type="varchar" Nullable="false" MaxLength="50" />
<Property Name="LanguageFrom" Type="int" Nullable="false" />
<Property Name="LanguageTo" Type="int" Nullable="false" />
</EntityType>
然后有一个伙伴类来扩展它:
[MetadataType(typeof(JobValidation))]
[Bind(Include = "Client,SentDate,JobFileName,JobDescription,WordCost,WordCount,WorkedBy")]
public partial class Job
{
public IEnumerable Clients
{
get
{
var clientRepository = new ClientRepository();
return clientRepository.GetAllClients();
}
}
public string ClientName { get; set; }
public string SelectedMonth { get; set; }
public string SelectedYear { get; set; }
}
public class JobValidation
{
[Required(ErrorMessage = "Please select a client for the sent job")]
[Range(1, 999999, ErrorMessage = "Please select a client")]
public int Client { get; set; }
[Required(ErrorMessage = "Please enter the completion date for this job")]
[DataType(DataType.Date, ErrorMessage = "The date entered is not in a recognised format")]
public DateTime SentDate { get; set; }
[Required(ErrorMessage = "Job file must have a name")]
[StringLength(500, ErrorMessage = "Job file name must not be longer than 500 characters")]
public string JobFileName { get; set; }
[Required(ErrorMessage = "Job must have a name")]
[StringLength(200, ErrorMessage = "Job name must not be longer than 200 characters")]
public string JobDescription { get; set; }
[Required(ErrorMessage = "Please enter the word cost for the sent job")]
[StringLength(6, ErrorMessage = "The word cost should not exceed 5 digits")]
[DataType(DataType.Currency, ErrorMessage = "The word cost was not recognised as an amount of currency")]
public string WordCost { get; set; }
[Required(ErrorMessage = "Please enter the word count for the sent job")]
[StringLength(8, ErrorMessage = "The word count must not exceed 99999999")]
public string WordCount { get; set; }
public string WorkedBy { get; set; }
}
最后,这是视图的相关部分:
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Job Details</legend>
<div class="editor-label">
Job description
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.JobDescription)%>
<%: Html.ValidationMessageFor(model => model.JobDescription)%>
</div>
<div class="editor-label">
PO number
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.PONumber)%>
<%: Html.ValidationMessageFor(model => model.PONumber)%>
</div>
<div class="editor-label">
Date received
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.ReceivedDate)%>
<%: Html.ValidationMessageFor(model => model.ReceivedDate)%>
</div>
<div class="editor-label">
Deadline Date
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.DeadlineDate)%>
<%: Html.ValidationMessageFor(model => model.DeadlineDate)%>
</div>
<div class="editor-label">
Date sent
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.SentDate)%>
<%: Html.ValidationMessageFor(model => model.SentDate)%>
</div>
<div class="editor-label">
Is fixed-cost? <input type="checkbox" id="fixed-cost" />
</div>
<div id="word-priced-job">
<div class="editor-label">
Word count
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.WordCount)%>
<%: Html.ValidationMessageFor(model => model.WordCount)%>
</div>
<div class="editor-label">
Word cost
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.WordCost)%>
<%: Html.ValidationMessageFor(model => model.WordCost)%>
</div>
</div>
<div id="fixed-price-job" class="faded">
<div class="editor-label">
Fixed cost
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.FixedCost)%>
<%: Html.ValidationMessageFor(model => model.FixedCost)%>
</div>
</div>
<div class="editor-label">
Languages
</div>
<div class="editor-field">
<%: Html.DropDownListFor(model => model.LanguageFrom, Model.Languages, "-- Select --") %><%: Html.ValidationMessageFor(model => model.LanguageFrom)%>
<span> - to - </span>
<%: Html.DropDownListFor(model => model.LanguageTo, Model.Languages, "-- Select --") %><%: Html.ValidationMessageFor(model => model.LanguageTo)%>
</div>
<div class="editor-label">
Client
</div>
<div class="editor-field">
<%: Html.DropDownListFor(model => model.Client, Model.ClientsList, "-- Select --") %> <%: Html.ActionLink("Create a new client", "Create", "Clients") %>
<%: Html.ValidationMessageFor(model => model.Client)%>
</div>
<div class="editor-label">
Job file name
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.JobFileName) %>
<%: Html.ValidationMessageFor(model => model.JobFileName)%>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.WorkedBy)%>
</div>
<div class="editor-field">
<%: Html.DropDownListFor(model => model.WorkedBy, Model.Users) %>
</div>
<p>
<input id="btnSave" type="submit" value="Save" />
</p>
</fieldset>
<% } %>
I have a view which accepts the following model:
Inherits="System.Web.Mvc.ViewPage<MVC_WordsByME.Models.JobCreationModel>"
This posts back to the following action:
[HttpPost]
public ActionResult Create(FormCollection formValues)
{
var job = new JobCreationModel();
if (TryUpdateModel(job))
{
_jobRepository.AddJob(job);
_jobRepository.Save();
return RedirectToAction("Index");
}
return View(job);
}
However, on posting back the following exception is thrown:
Unable to cast object of type 'System.Int32' to type 'System.String'.
Description: An unhandled exception occurred during the execution of the current web request.
Please review the stack trace for more information about the error and where it originated in the code.Exception Details: System.InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.String'.
Source Error:
Line 135: {
Line 136: var job = new JobCreationModel();
Line 137: if (TryUpdateModel(job))
Line 138: {
Line 139: _jobRepository.AddJob((Job)job);
Although I can't highlight it here, it's line 137 that the exception occurs on. I can't step into this method, so how can I determine what's causing this exception?
Also, isn't TryUpdateModel supposed to shelter me from any exceptions, simply returning true or false to reflect the result? I wasn't aware that it could throw an exception.
UPDATE: here's the model (both derived and base):
public class JobCreationModel : Job
{
//
// Properties
public SelectList ClientsList { get; private set; }
public SelectList Languages { get; set; }
public SelectList Users { get; set; }
//
// Constructors
public JobCreationModel()
{
var userCurrent = Membership.GetUser();
SentDate = DateTime.Now;
WorkedBy = userCurrent != null ? userCurrent.UserName : string.Empty;
DeadlineDate = DateTime.Now;
ReceivedDate = DateTime.Now;
var clientRepository = new ClientRepository();
ClientsList = new SelectList(clientRepository.GetAllClients(), "ID", "OrganisationName");
var languageRepository = new LanguageRepository();
Languages = new SelectList(languageRepository.GetAllLanguages(), "ID", "Code");
var userList = Membership.GetAllUsers();
Users = new SelectList(userList.Cast<MembershipUser>().ToList(), "UserName", "UserName", userCurrent);
}
public JobCreationModel(Job job)
{
var userCurrent = Membership.GetUser();
Client = job.Client;
ClientName = job.ClientName;
DeadlineDate = job.DeadlineDate;
FixedCost = job.FixedCost;
ID = job.ID;
Invoice = job.Invoice;
JobDescription = job.JobDescription;
JobFileName = job.JobFileName;
LanguageFrom = job.LanguageFrom;
LanguageTo = job.LanguageTo;
PONumber = job.PONumber;
ReceivedDate = job.ReceivedDate;
SentDate = job.SentDate;
WordCost = job.WordCost;
WordCount = job.WordCount;
WorkedBy = job.WorkedBy;
var clientRepository = new ClientRepository();
ClientsList = new SelectList(clientRepository.GetAllClients(), "ID", "OrganisationName");
var languageRepository = new LanguageRepository();
Languages = new SelectList(languageRepository.GetAllLanguages(), "ID", "Code");
var userList = Membership.GetAllUsers();
Users = new SelectList(userList.Cast<MembershipUser>().ToList(), "UserName", "UserName", userCurrent);
}
}
The base type is an entity, and the best way I could think of to show it is to display the XML behind it:
<EntityType Name="Jobs">
<Key>
<PropertyRef Name="ID" />
</Key>
<Property Name="ID" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
<Property Name="JobDescription" Type="nvarchar" Nullable="false" MaxLength="200" />
<Property Name="ReceivedDate" Type="datetime" Nullable="false" />
<Property Name="DeadlineDate" Type="datetime" Nullable="false" />
<Property Name="SentDate" Type="datetime" Nullable="false" />
<Property Name="Invoice" Type="int" />
<Property Name="WordCount" Type="int" Nullable="false" />
<Property Name="WordCost" Type="float" Nullable="false" />
<Property Name="FixedCost" Type="float" Nullable="false" />
<Property Name="Client" Type="int" Nullable="false" />
<Property Name="JobFileName" Type="nvarchar" Nullable="false" MaxLength="500" />
<Property Name="WorkedBy" Type="varchar" Nullable="false" MaxLength="50" />
<Property Name="PONumber" Type="varchar" Nullable="false" MaxLength="50" />
<Property Name="LanguageFrom" Type="int" Nullable="false" />
<Property Name="LanguageTo" Type="int" Nullable="false" />
</EntityType>
This then has a buddy class to extend it:
[MetadataType(typeof(JobValidation))]
[Bind(Include = "Client,SentDate,JobFileName,JobDescription,WordCost,WordCount,WorkedBy")]
public partial class Job
{
public IEnumerable Clients
{
get
{
var clientRepository = new ClientRepository();
return clientRepository.GetAllClients();
}
}
public string ClientName { get; set; }
public string SelectedMonth { get; set; }
public string SelectedYear { get; set; }
}
public class JobValidation
{
[Required(ErrorMessage = "Please select a client for the sent job")]
[Range(1, 999999, ErrorMessage = "Please select a client")]
public int Client { get; set; }
[Required(ErrorMessage = "Please enter the completion date for this job")]
[DataType(DataType.Date, ErrorMessage = "The date entered is not in a recognised format")]
public DateTime SentDate { get; set; }
[Required(ErrorMessage = "Job file must have a name")]
[StringLength(500, ErrorMessage = "Job file name must not be longer than 500 characters")]
public string JobFileName { get; set; }
[Required(ErrorMessage = "Job must have a name")]
[StringLength(200, ErrorMessage = "Job name must not be longer than 200 characters")]
public string JobDescription { get; set; }
[Required(ErrorMessage = "Please enter the word cost for the sent job")]
[StringLength(6, ErrorMessage = "The word cost should not exceed 5 digits")]
[DataType(DataType.Currency, ErrorMessage = "The word cost was not recognised as an amount of currency")]
public string WordCost { get; set; }
[Required(ErrorMessage = "Please enter the word count for the sent job")]
[StringLength(8, ErrorMessage = "The word count must not exceed 99999999")]
public string WordCount { get; set; }
public string WorkedBy { get; set; }
}
Finally, here's the relevant part of the view:
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Job Details</legend>
<div class="editor-label">
Job description
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.JobDescription)%>
<%: Html.ValidationMessageFor(model => model.JobDescription)%>
</div>
<div class="editor-label">
PO number
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.PONumber)%>
<%: Html.ValidationMessageFor(model => model.PONumber)%>
</div>
<div class="editor-label">
Date received
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.ReceivedDate)%>
<%: Html.ValidationMessageFor(model => model.ReceivedDate)%>
</div>
<div class="editor-label">
Deadline Date
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.DeadlineDate)%>
<%: Html.ValidationMessageFor(model => model.DeadlineDate)%>
</div>
<div class="editor-label">
Date sent
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.SentDate)%>
<%: Html.ValidationMessageFor(model => model.SentDate)%>
</div>
<div class="editor-label">
Is fixed-cost? <input type="checkbox" id="fixed-cost" />
</div>
<div id="word-priced-job">
<div class="editor-label">
Word count
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.WordCount)%>
<%: Html.ValidationMessageFor(model => model.WordCount)%>
</div>
<div class="editor-label">
Word cost
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.WordCost)%>
<%: Html.ValidationMessageFor(model => model.WordCost)%>
</div>
</div>
<div id="fixed-price-job" class="faded">
<div class="editor-label">
Fixed cost
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.FixedCost)%>
<%: Html.ValidationMessageFor(model => model.FixedCost)%>
</div>
</div>
<div class="editor-label">
Languages
</div>
<div class="editor-field">
<%: Html.DropDownListFor(model => model.LanguageFrom, Model.Languages, "-- Select --") %><%: Html.ValidationMessageFor(model => model.LanguageFrom)%>
<span> - to - </span>
<%: Html.DropDownListFor(model => model.LanguageTo, Model.Languages, "-- Select --") %><%: Html.ValidationMessageFor(model => model.LanguageTo)%>
</div>
<div class="editor-label">
Client
</div>
<div class="editor-field">
<%: Html.DropDownListFor(model => model.Client, Model.ClientsList, "-- Select --") %> <%: Html.ActionLink("Create a new client", "Create", "Clients") %>
<%: Html.ValidationMessageFor(model => model.Client)%>
</div>
<div class="editor-label">
Job file name
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.JobFileName) %>
<%: Html.ValidationMessageFor(model => model.JobFileName)%>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.WorkedBy)%>
</div>
<div class="editor-field">
<%: Html.DropDownListFor(model => model.WorkedBy, Model.Users) %>
</div>
<p>
<input id="btnSave" type="submit" value="Save" />
</p>
</fieldset>
<% } %>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在没有看到模型和视图代码的情况下不知道为什么会发生此异常,但请尝试像这样简化您的操作:
No idea why this exception occurs without seeing your model and view code but try simplifying your action like this:
我已将: 更改
为:
那么 StringLength 属性会产生问题,因为 GroupID 是 int?看来 StringLength 属性仅对字符串有效。
I've changed:
to:
So the StringLength attribute made problems, because GroupID was int? and as it seems StringLength attribute is valid only for strings.