调用 UpdateModel() 时如何从绑定中排除属性?

发布于 2024-12-18 18:08:09 字数 1421 浏览 2 评论 0原文

我有一个视图模型发送到我的控制器的编辑操作。 ViewModel 包含对 EntityObject 的引用。 (是的,我对此很满意,不需要复制视图模型中的所有实体属性)。

我实例化视图模型,然后调用 UpdateModel。我收到一个错误,指出属性为“null”,这很好,因为它是相关模型。我试图在模型绑定期间排除该属性的绑定。在调试它时,我在实体中看到模型绑定程序试图将属性的值设置为 null。

这是我的编辑操作:

var model = new SimplifiedCompanyViewModel(id);

var excludeProperties = new string[] { 
   "Entity.RetainedEarningsAccount.AccountNo"
   ,"Property.DiscountEarnedAccount.ExpenseCodeValue"
   ,"Entity.EntityAlternate.EntityID"
   ,"Property.BankAccount.BankAccountID"
   ,"Entity.PLSummaryAccount.AccountNo"
   ,"Property.RefundBank.BankAccountID"
   ,"Company.Transmitter.TCC"
};

try
{
    UpdateModel<SimplifiedCompanyViewModel>(model, String.Empty, null, excludeProperties);

    if (ModelState.IsValid)
    {
       //db.SaveChanges();
    }
       return RedirectToAction("Index");
}
catch
{
    return View(model);
}

我已经研究了有关指定“前缀”的其他一些问题,但我认为这不是问题,因为我告诉它绑定到视图模型实例而不仅仅是实体对象。

我是否正确排除了这些属性?奇怪的是,似乎只发生在这个项目上。我怀疑这可能是因为实际上没有与我的实体相关的退款银行。但我还有其他不存在的相关项目,并且没有看到相同的问题。

更多信息...因为我被告知模型设计得不好。

该公司与银行账户相关。 Company 视图显示当前相关的 BankAccount.BankAccountId,并且有一个包含 BankAccount.Key 的隐藏字段。我使用 jQueryUI 自动完成功能来提供显示 BankAccount.BankAccountId 的银行帐户下拉列表,当选择一个时,jQuery 代码会更改隐藏字段以具有正确的键值。因此,当发布此信息时,我不希望修改当前的银行帐户 BankAccountID,因此我希望它跳过绑定该字段。

如果我在模型中排除 BankAccountId,则在 BankAccount 编辑视图上,用户将永远无法更改 BankAccountId,因为它不会被绑定。我不确定这如何表明模型设计不佳。

I have a view model sent to the edit action of my controller. The ViewModel contains references to EntityObjects. (yea i'm fine with it and don't need to want to duplicate all the entities properties in the viewmodel).

I instantiate the view model and then call UpdateModel. I get an error that a property is "null" which is fine since it is a related model. I am trying to exclude the property from being bound during model binding. On debugging it I see in the entity where the model binder is trying to set the value of the property to null.

Here is my edit action:

var model = new SimplifiedCompanyViewModel(id);

var excludeProperties = new string[] { 
   "Entity.RetainedEarningsAccount.AccountNo"
   ,"Property.DiscountEarnedAccount.ExpenseCodeValue"
   ,"Entity.EntityAlternate.EntityID"
   ,"Property.BankAccount.BankAccountID"
   ,"Entity.PLSummaryAccount.AccountNo"
   ,"Property.RefundBank.BankAccountID"
   ,"Company.Transmitter.TCC"
};

try
{
    UpdateModel<SimplifiedCompanyViewModel>(model, String.Empty, null, excludeProperties);

    if (ModelState.IsValid)
    {
       //db.SaveChanges();
    }
       return RedirectToAction("Index");
}
catch
{
    return View(model);
}

I have looked at a few other issues about specifying a "prefix" but I don't think that is the issue since I am telling it to bind to the viewmodel instance not just the entity object.

Am I excluding the properties correctly? Strange thing is is only seems to happen on this item. I suspect it may be an issue with the fact that there is actually no refund bank related to my entity. But I have other related items that don't exist and don't see the same issue.

More info... since I'm told me model isn't designed well.

The Company is related to a BankAccount. The Company view shows the currently related BankAccount.BankAccountId and there is a hidden field with the BankAccount.Key. I use jQueryUI autocomplete feature to provide a dropdown of bank account displaying the BankAccount.BankAccountId and when one is selected the jQuery code changes the hidden field to have the correct Key value. So, when this is posted I don't want the current bankaccounts BankAccountID modified, hence I want it to skip binding that field.

If I exclude BankAccountId in the model then on the BankAccount edit view the user would never be able to change the BankAccountId since it won't be bound. I'm not sure how this indicates a poor model design.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

秋风の叶未落 2024-12-25 18:08:09

使用 排除 绑定 属性:

[Bind(Exclude="Id,SomeOtherProperty")]
public class SimplifiedCompanyViewModel
{
    public int Id { get; set; }

    // ...
}

这是 System.Web.Mvc 命名空间的一部分。绑定时需要排除以逗号分隔的属性名称列表。

您还应该考虑使用 TryUpdateModel 而不是 UpdateModel。您还可以通过将默认模型绑定程序作为参数传递给构造函数来计算它:

public ActionResult Create([Bind(Exclude="Id")]SimplifiedCompanyViewModel model)
{
    // ...
}

Use the Exclude property of the Bind attribute:

[Bind(Exclude="Id,SomeOtherProperty")]
public class SimplifiedCompanyViewModel
{
    public int Id { get; set; }

    // ...
}

This is part of the System.Web.Mvc namespace. It takes a comma-separated list of property names to exclude when binding.

Also you should consider using TryUpdateModel instead of UpdateModel. You can also just have the default model binder figure it out by passing it as an argument to the constructor:

public ActionResult Create([Bind(Exclude="Id")]SimplifiedCompanyViewModel model)
{
    // ...
}
往事随风而去 2024-12-25 18:08:09

我想出了一个非常简单的解决方案。

 try
{
   UpdateModel<SimplifiedCompanyViewModel>(model, String.Empty, null, excludeProperties);
   ModelState.Remove("Entity.RetainedEarningsAccount.AccountNo");
   ModelState.Remove("Property.DiscountEarnedAccount.ExpenseCodeValue");
   ModelState.Remove("Entity.EntityAlternate.EntityID");
   ModelState.Remove("Property.BankAccount.BankAccountID");
   ModelState.Remove("Entity.PLSummaryAccount.AccountNo");
   ModelState.Remove("Property.RefundBank.BankAccountID");
   ModelState.Remove("ompany.Transmitter.TCC");

    if (ModelState.IsValid)
    {
       //db.SaveChanges();
    }
       return RedirectToAction("Index");
}
catch
{
    return View(model);
}

A very simple solution that I figured out.

 try
{
   UpdateModel<SimplifiedCompanyViewModel>(model, String.Empty, null, excludeProperties);
   ModelState.Remove("Entity.RetainedEarningsAccount.AccountNo");
   ModelState.Remove("Property.DiscountEarnedAccount.ExpenseCodeValue");
   ModelState.Remove("Entity.EntityAlternate.EntityID");
   ModelState.Remove("Property.BankAccount.BankAccountID");
   ModelState.Remove("Entity.PLSummaryAccount.AccountNo");
   ModelState.Remove("Property.RefundBank.BankAccountID");
   ModelState.Remove("ompany.Transmitter.TCC");

    if (ModelState.IsValid)
    {
       //db.SaveChanges();
    }
       return RedirectToAction("Index");
}
catch
{
    return View(model);
}
抚你发端 2024-12-25 18:08:09

这里的另一个选择是不要在您的视图中包含此属性,并且它不会被绑定。是的 - 如果有人在页面上创建模型注入,您仍然愿意接受模型注入,但这是另一种选择。 MVC 中的默认模板会将 EditorFor 等创建为单独的项目,因此您可以删除它们。这会阻止您将单行视图编辑器与 EditorForModel 一起使用,但模板无论如何都不会以这种方式生成它。

编辑(添加上面的评论)

DRY 通常适用于逻辑,而不是视图模型。一种视图=一种视图模型。使用自动映射器可以轻松地在它们之间进行映射。 Jimmy Bogard 对此有一个很棒的属性,使其几乎是自动的 - 即,您创建视图模型,加载您的 Customer 实体,然后在操作方法中返回它。然后,AutpMap 属性会将其转换为 ViewModel。请参阅 lostechies.com/jimmybogard/2009/06 /30/how-we-do-mvc-view-models

Another option here is simply don't include this attribute in your view and it won't be bound. Yes - you are still open to model injection then if someone creates it on the page but it is another alternative. The default templates in MVC will create your EditorFor, etc as separate items so you can just remove them. This prevents you from using a single line view editor with EditorForModel, but the templates don't generate it that way for you anyways.

EDIT (adding above comment)

DRY generally applies to logic, not to view models. One view = one view model. Use automapper to easily map between them. Jimmy Bogard has a great attribute for this that makes it almost automatic - ie you create the view model, load up your Customer entity for example, and return it in the action method. The AutpMap attribute will then convert it to a ViewModel. See lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models

因为看清所以看轻 2024-12-25 18:08:09

尝试排除 属性。
我承认我没用过。

[Exclude]
public Entity Name {get; set;}

Try the Exclude attribute.
I admit that I haven't ever used it.

[Exclude]
public Entity Name {get; set;}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文