문제

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