MVC ViewModel,使用具有标记所需的某些属性的VM,具体取决于其是否为GET或POST

时间:2015-07-18 10:24:36

标签: c# asp.net-mvc validation viewmodel modelstate

我经常发现自己手动修复模型状态的验证,因为在发布和获取期间视图模型中需要的某些字段不一致。

假设我有这个视图模型:

public class RestaurantMenuName_ViewModel
{        
    public Int64 RestaurantMenuNameId { get; set; }

    public Int64 OwnerId{ get; set; }

    public string MenuNameCategory { get; set; }

    public string CategoryDescription { get; set; }

    public bool IsFormSaved { get; set; }
} 

GET 请求期间,控制器/操作只需要验证字段,RestaurantMenuNameId和OwnerId。调用Action RestaurantMenuName时,查询字符串值为RestaurantMenuNameId和OwnerId。 Modelstate验证将在以下时间完成:

  • RestaurantMenuNameId
  • OWNERID

POST 请求期间,控制器/操作将需要对字段进行模型状态验证:

  • RestaurantMenuNameId
  • OWNERID
  • MenuNameCategory
  • CategoryDe​​scription

这是我所讨论的不一致问题,解决方案可能是使用ViewModel进行Get请求,而使用一个用于Post,但这可能是真正浪费时间并且容易出错。使用ViewBag是不可能的。

问题: 有没有办法告诉MVC我们想要一些字段[必需]用于GET和其他用于POST?

以下是我所谈论的伪代码:

 public class RestaurantMenuName_ViewModel
{   
    [Required: in GET, POST]  //<--Pseudo code
    public Int64 RestaurantMenuNameId { get; set; }

    [Required: in GET, POST]  //<--Pseudo code
    public Int64 OwnerId { get; set; }

    [Required: in POST]       //<--Pseudo code
    public string MenuNameCategory { get; set; }

    [Required: in POST]       //<--Pseudo code
    public string CategoryDescription { get; set; }

    public bool IsFormSaved { get; set; }
} 

1 个答案:

答案 0 :(得分:2)

当您只需要很少的属性时,传递复杂对象并不是一个很好的做法(在您的情况下会令人困惑)。最好只传递所需的id作为原语。

如果案例很特殊并且您确实需要复杂的对象,那么最好为每个请求创建两个不同的视图模型并相应地修饰所需的属性。

但是,您可以创建自己的require验证属性,该属性将根据当前请求验证属性。

public class MyRequiredAttribute : ValidationAttribute
{
    private string httpVerb;

    public MyRequiredAttribute(string httpVerb)
    {
        this.httpVerb = httpVerb;
    }

    public override bool IsValid(object value)
    {
        if(HttpContext.Current.Request.HttpMethod == this.httpVerb)
        {
            return value != null;
        }

        return true;
    }
}

// Usage
public class MyViewModel
{
    [MyRequired("GET")]
    public string A { get; set; }

    [MyRequired("POST")]
    public string B { get; set; }
}

注意:您可以使用枚举来避免一些困难(例如大写,小写,拼写错误等),还可以覆盖FormatErrorMessage方法来更改默认值错误消息并正确格式化。