MVC - 使用ViewModel进行验证(Model.State)

时间:2015-11-25 18:30:07

标签: c# asp.net-mvc validation

我需要一些帮助。我有以下情况,我认为我做错了。

- 模型“状态”

    namespace App.Model
    {
        public class State
        {

            [Key]
            [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
            public int idState { get; set; }

            [Required(ErrorMessage = "Initials is required")]
            public string StateInitials { get; set; }

            [Required(ErrorMessage = "Name is required")]
            public string StateName { get; set; }

            [Display(Name = "Update Date")]
            [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}")]
            public DateTime? UpdateDate { get; set; }

            [Display(Name = "Update Responsible")]
            public string UpdateResponsible { get; set; }

        } //class

    } //namespace

- 模型“位置”

    namespace App.Model
    {
        public class Location
        {

            [Key]
            [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
            public int idLocation { get; set; }

            public int idState { get; set; }

            [Required(ErrorMessage = "Name is required")]
            public string LocationName { get; set; }

            public string Status { get; set; }
            public string ManagerName { get; set; }
            public string Address { get; set; }

            [Display(Name = "Update Date")]
            [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}")]
            public DateTime? UpdateDate { get; set; }

            [Display(Name = "Update Responsible")]
            public string UpdateResponsible { get; set; }

        } //class

    } //namespace

State和Location之间的关系是一对多,但我没有在模型上描述这个(使用导航字段)。

我有一个视图,我想编辑位置。为此,我使用以下视图模型。

- 查看模型“LocationsViewModel”

    namespace App.ViewModel
    {
        public class LocationsViewModel
        {

            public State objState { get; set; }

            public List<Location> lstLocations { get; set; }

        } //class

    } //namespace

要编辑位置,请使用以下控制器。

namespace App.Controllers
{

  public class LocationController : Controller
  {

    private DbContext db = new DbContext();

    // GET: /Location/Edit/5
    public ActionResult Edit(int? id)
    {

        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }

        State objState = db.States.Find(id);

        if (objState == null)
        {
            return HttpNotFound();
        }

        LocationsViewModel model = new LocationsViewModel();
        model.objState = objState;
        model.lstLocations = getLocations(objState.idState);  //I didn´t show this method here just to simplify

        return View(model);

    } //Edit

    // POST: /Location/Edit/5
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Editar(LocationsViewModel model)
    {

        State objState = db.States.Find(model.objState.idState);

        try
        {

            if (ModelState.IsValid)
            {

                //Saving Locations
                foreach (Location obj in model.lstLocations)
                {

                    Location objLocation =  db.Locations.Find(obj.idLocation);
                    objLocation.LocationName = obj.LocationName;
                    objLocation.Status = obj.Status;
                    objLocation.ManagerName = obj.ManagerName;
                    objLocation.Address = obj.Address;

                    objLocation.UpdateDate = DateTime.Now;
                    objLocation.UpdateResponsible = User.Identity.Name;
                    db.Entry(objLocation).State = EntityState.Modified;

                    db.SaveChanges();

                } //foreach

                return RedirectToAction("Index");

            }

        }
        catch (Exception e)
        {
            ModelState.AddModelError("", e.Message);
        }

        model.objState = objState;
        model.lstLocations = getLocations(objState.idState);  //I didn´t show this method here just to simplify

        return View(model);

    } //Edit

} //class

} //namespace

问题/问题是:

我编写此代码来编辑(保存)特定州的位置列表。当我提交“编辑”视图时,MVC也会尝试验证位置列表(lstLocations)和状态(objState),但我想验证位置列表。

注1。我需要将两个对象传递给我的编辑视图:objState和lstLocations。我需要objState对象,因为我在页面(视图)上向用户显示了一些State属性。

注2。我的 ModelState.IsValid = false 因为 model.objLocation 无效,但我不想要检查objLocation(与此视图无关)。我只想查看位置列表(lstLocation)

实现我的最佳方法是什么?难道我做错了什么?我需要改变自己的思维方式吗?

2 个答案:

答案 0 :(得分:2)

你需要两件事。第一种是从ModelState中删除您不想验证的对象。第二个是你需要在if(ModelState.IsValid)块中放置要在有效状态下执行的代码块。

public ActionResult Edit(int? id)
{
    //don't validate this field
    ModelState.Remove("yourObject.property"); 

    if (ModelState.IsValid)
    {
        ...
    }
}

答案 1 :(得分:0)

除了您已经选择的解决方案之外,我发现自定义RequiredIfAttribute很有用。使用它,你可以根据另一个条件控制是否需要某些东西,例如:

...
public bool RequireLocationName {
   get {
       return !Addresses.Any();
   }
}

[RequiredIf("RequireLocationName", true)]
public bool LocationName { get; set; }