使用ASP.NET MVC,我有一个模型,我正在附加属性,以便我可以使用MVC模型绑定验证,但是并不是这个突破mvc的规则,你把属于视图的物品放入模型?我希望我不是聪明的聪明,但是对其他的意见感到好奇。

public class Payments
{
    [DataType(DataType.Text)]
    [DisplayFormat(NullDisplayText="")]
    [Display(Name="Payment Id")]
    [Required(ErrorMessage="Required")]
    public int PaymentId { get; set; } //todo: make this into a dropdown

    [DataType(DataType.Text)]
    [Display(Name="Bill Name")]
    [Required(ErrorMessage = "Required")]
    public string PaymentName { get; set; }

    [DataType(DataType.Date)]
    [Display(Name="Date to Post Payment")]
    [Required(ErrorMessage = "Required")]
    public DateTime PaymentDate { get; set; }

    [DataType(DataType.Currency)]
    [Range(0, 922337203685477.5807)]
    [Required(ErrorMessage = "Required")]
    public double PaymentAmount { get; set; }
}
.

有帮助吗?

解决方案

Yes. Thats why you should use ViewModels.

其他提示

You can, but don't have to, put those validation attributes in your model.

But it's better to use a ViewModel:

public class PaymentsViewModel
{
    [DataType(DataType.Text)]
    [DisplayFormat(NullDisplayText="")]
    [Display(Name="Payment Id")]
    [Required(ErrorMessage="Required")]
    public int PaymentId { get; set; } //todo: make this into a dropdown

    [DataType(DataType.Text)]
    [Display(Name="Bill Name")]
    [Required(ErrorMessage = "Required")]
    public string PaymentName { get; set; }

    [DataType(DataType.Date)]
    [Display(Name="Date to Post Payment")]
    [Required(ErrorMessage = "Required")]
    public DateTime PaymentDate { get; set; }

    [DataType(DataType.Currency)]
    [Range(0, 922337203685477.5807)]
    [Required(ErrorMessage = "Required")]
    public double PaymentAmount { get; set; }
}

And in your View, instead of:

@model YourProject.Models.Payments

you use:

@model YourProject.Models.PaymentsViewModel

for validation.

Does it violate MVC in the strict sense, yeah, probably. Are there times when there's no harm in violating that? Sure. However, there are mechanisms to help you out and keep the concerns separate.

You can use your persisted domain objects in the views and validate against them, but when your view starts getting complicated, ViewModels become a necessity. For dead simple domain models or view-only views (not edits/creates), I'll sometimes fudge a bit and send them into the view as part of a composite object:

class MyViewModel
{
    public MyDomainModel DomainObj;
    public int OtherViewInfo;
}

However, for create and edit scenarios, ViewModels are far better. They allow you total control over the data being sent to the view and from the view.

If you are using EF 4.1 and CodeFirst, then yes, you'll end up with some duplication of attributes and properties between the domain and the ViewModel. This is unavoidable but gives you the flexibility of doing different validations specific to the view.

I've found it useful to have one extra layer of protection in the controller when actually saving the domain object in case I missed some validation in the view:

public class MyController : Controller
{
    [HttpPost]
    public ActionResult Edit(int id, MyViewModel model)
    {
        try
        {
            ...Do stuff, check ModelState.IsValid...
            _context.SaveChanges()
        }
        catch (DbEntityValidationException dbEx)
        {
            // Catch any validation errors on the domain that weren't duplicated
            // in the viewmodel
            ModelState.AddModelError("Form", dbEx);
        }

        return View(model);
    }
}

The next question to ask is how you map between the domain model and the ViewModel. There are a number of strategies and tools out there - AutoMapper and ValueInjecter (yes, spelled wrong). Personally, I've been using ValueInjecter although if you setup a mapping layer, you can try both. I've found that neither will work in 100% of cases, or at least I could figure out how to do what I needed, but a mapping service makes it easy to define custom left-to-right maps.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top