ASP.NET MVC 模型验证违反了 MVC 规则?

发布于 2024-11-07 16:51:12 字数 1105 浏览 0 评论 0原文

使用 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; }
}

using ASP.NET MVC, I have a Model, to which I'm attaching attributes so that I can get use the MVC Model bound validation, but to doesn't this break the rule of MVC, where you are putting items that belong to the View, into the Model? I hope I don't come of as trying to be smart, I am however curious as to other's opinions.

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; }
}

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

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

发布评论

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

评论(3

烛影斜 2024-11-14 16:51:12

是的。这就是为什么你应该使用 ViewModel。

Yes. Thats why you should use ViewModels.

成熟的代价 2024-11-14 16:51:12

您可以(但不必)将这些验证属性放入模型中。

但最好使用 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; }
}

在您的视图中,而不是:

@model YourProject.Models.Payments

您使用:

@model YourProject.Models.PaymentsViewModel

进行验证。

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.

红玫瑰 2024-11-14 16:51:12

从严格意义上讲,它是否违反了 MVC,是的,可能是。有时违反这一点也没有什么坏处吗?当然。但是,有一些机制可以帮助您解决问题并将问题分开。

您可以在视图中使用持久化的域对象并对其进行验证,但是当您的视图开始变得复杂时,ViewModel 就成为必需品。对于死简单的域模型或仅查看视图(不是编辑/创建),我有时会稍微修改一下并将它们作为复合对象的一部分发送到视图中:

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

但是,对于创建和编辑场景,ViewModel 要好得多。它们允许您完全控制发送到视图以及从视图发送的数据。

如果您使用 EF 4.1 和 CodeFirst,那么是的,您最终会在域和 ViewModel 之间出现一些属性和属性的重复。这是不可避免的,但可以让您灵活地执行特定于视图的不同验证。

我发现在实际保存域对象时在控制器中提供一层额外的保护很有用,以防我错过了视图中的某些验证:

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);
    }
}

下一个要问的问题是如何在域模型和 ViewModel 之间映射。有许多策略和工具 - AutoMapperValueInjecter (是的,拼写错误)。就我个人而言,我一直在使用 ValueInjecter,尽管如果您设置了映射层,则可以同时尝试两者。我发现这两种方法都不能在 100% 的情况下工作,或者至少我可以弄清楚如何做我需要的事情,但是地图服务可以轻松定义自定义从左到右的地图。

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.

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