我在编辑相关对象的属性时遇到一些问题。这是代码:
型号:
的 DocumentLine.cs 的
/// <summary>
/// States the base implementation for all document lines in a purchasing module.
/// </summary>
public class DocumentLine : Keyed
{
// ... some other properties
/// <summary>
/// Gets or sets the current line's document header.
/// </summary>
[Navigation]
[Display(ResourceType = typeof(Resources.ApplicationResources), Name = "Header")]
public virtual DocumentHeader Header { get; set; }
}
的 DocumentHeader.cs 的
/// <summary>
/// States the base implementation for all document headers in a purchasing module.
/// </summary>
public class DocumentHeader : Keyed
{
/// <summary>
/// Gets or sets the current header's document number.
/// </summary>
[Required]
[Display(ResourceType = typeof(Resources.ApplicationResources), Name = "DocumentNumber")]
public string DocumentNumber { get; set; }
/// <summary>
/// Gets or sets the extra cost of the document.
/// </summary>
[Display(ResourceType = typeof(Resources.ApplicationResources), Name = "ExtraCost")]
[RegularExpression(@"^\d*$", ErrorMessageResourceType=typeof(Resources.ApplicationResources), ErrorMessageResourceName= "Exception_ExtraCost_Error")]
public decimal ExtraCost { get; set; }
/// <summary>
/// Gets or sets the vat's extra cost of the document.
/// </summary>
[Display(ResourceType = typeof(Resources.ApplicationResources), Name = "ExtraVat")]
[RegularExpression(@"^\d*$", ErrorMessageResourceType = typeof(Resources.ApplicationResources), ErrorMessageResourceName = "Exception_ExtraVat_Error")]
public decimal ExtraVat { get; set; }
/// <summary>
/// Gets or sets the navigation property to all dependant Document lines.
/// </summary>
[Required]
[Navigation]
[Display(ResourceType = typeof(Resources.ApplicationResources), Name = "DocumentLines")]
public virtual ICollection<DocumentLine> DocumentLines { get; set; }
}
查看:
@Html.HiddenFor(model => model.Header.Id, Model.Header != null ? Model.Header.Id : null)
<div class="display-label">
@Html.DisplayNameFor(model => model.Header.ExtraCost)
</div>
<div class="display-field">
<input type="text" name="Header.ExtraCost" id="Header.ExtraCost" data-varname="header.extraCost" value="@(Model.Header.ExtraCost)" />
@Html.ValidationMessageFor(model => model.Header.ExtraCost)
</div>
<div class="display-label">
@Html.DisplayNameFor(model => model.Header.ExtraVat)
</div>
<div class="display-field">
<input type="text" name="Header.ExtraVat" id="Header.ExtraVat" data-varname="header.extraVat" value="@(Model.Header.ExtraVat)" />
@Html.ValidationMessageFor(model => model.Header.ExtraVat)
</div>
我知道MVC跟踪输入的id和名称以将值传递给控制器,这就是我为Header.Id
值设置隐藏输入的原因。此视图正确显示值,因此我认为问题不在此处。
控制器:
我有一个通用的控制器方法来编辑哪个工作正常,虽然我可能不得不为这个特殊情况覆盖它。
/// <summary>
/// Handles the POST event for the Edit action, updating an existing TEntity object.
/// </summary>
/// <param name="id">Id of the TEntity object to update.</param>
/// <param name="model">TEntity object with properties updated.</param>
/// <returns>Redirection to the Index action if succeeded, the Edit View otherwise.</returns>
[HttpPost]
public virtual ActionResult Edit(string id, TEntity model)
{
var request = new RestSharp.RestRequest(Resource + "?id={id}", RestSharp.Method.PUT) { RequestFormat = RestSharp.DataFormat.Json }
.AddParameter("id", id, RestSharp.ParameterType.UrlSegment)
.AddBody(model);
var response = Client.Execute(request);
// Handle response errors
HandleResponseErrors(response);
if (Errors.Length == 0)
return RedirectToAction("Index");
else
{
ViewBag.Errors = Errors;
return View(model);
}
}
主要问题是此代码不仅没有编辑相关的对象值,而且也设置为使DocumentLine的Header.Id
值为空。
有什么建议吗?
答案 0 :(得分:0)
这个问题很可能出现在我的答案的最后一段,但是这里有一些其他技巧可以帮助你调试这样的问题..
查看Google Chrome中的网络标签,或下载Firebug for Firefox并查看您实际发布到该方法的内容,在方法上设置一个断点并确保该方法的参数实际上是获取值。
删除“标题”。从输入的名称和ID,实际使用 @ Html.EditorFor(model =&gt; model.ExtraCost) 代替。您尚未为编辑视图发布GET方法,断点此方法并确保将实体传递给视图。
如果你这样做,你只需要使用@ Html.HiddenFor(model =&gt; model.Id)
在你的视图中,Id将被发布为Id,在你的控制器中被称为id,thsi将不会绑定,所以我怀疑Id实际上从未真正过去到ActionResult。
答案 1 :(得分:0)
我不得不修改默认的RestSharp PUT方法,强制它首先更新文档标题,然后更新发票行。
/// PUT api/<controller>/5
/// <summary>
/// Upserts a InvoiceLine object and its DocumentHeader to the underlying DataContext
/// </summary>
/// <param name="id">Id of the InvoiceLine object.</param>
/// <param name="value">The InvoiceLine object to upsert.</param>
/// <returns>An HttpResponseMessage with HttpStatusCode.Ok if everything worked correctly. An exception otherwise.</returns>
public override HttpResponseMessage Put(string id, [FromBody]InvoiceLine value)
{
//If creation date is in UTC format we must change it to local time
value.DateCreated = value.DateCreated.ToLocalTime();
//update the document header if there is any change
var header = Database.Set<DocumentHeader>()
.FirstOrDefault(x => x.Id == value.Header.Id);
if (header != null)
{
value.Header.DocumentLines = header.DocumentLines;
value.Header.DocumentNumber = header.DocumentNumber;
Database.Entry<DocumentHeader>(header)
.CurrentValues.SetValues(value.Header);
}
else
{
Database.Set<DocumentHeader>().Add(value.Header);
}
// If entity exists, set current values to atomic properties
// Otherwise, insert as new
var entity = Database.Set<InvoiceLine>()
.FirstOrDefault(x => x.Id == id);
if (entity != null)
{
Database.Entry<InvoiceLine>(entity)
.CurrentValues.SetValues(value);
FixNavigationProperties(ref entity, value);
}
else
{
FixNavigationProperties(ref value);
Database.Set<InvoiceLine>().Add(value);
}
if (value is ISynchronizable)
(value as ISynchronizable).LastUpdated = DateTime.UtcNow;
// Save changes and handle errors
SaveChanges();
return new HttpResponseMessage(HttpStatusCode.OK);
}
这对我有用。希望有所帮助。