控制器参数不会变为空

时间:2013-12-19 18:44:26

标签: c# asp.net-mvc controller

我遇到了以下问题:

我有一个asp.net mvc 5控制器,参考类型作为参数:

    [Route("")]
    [HttpGet]
    public ActionResult GetFeeds(Location location)
    {
        if (location == null)
        {
            // init location or smth
        }

        // Do smth with location

        return new EmptyResult();
   }

您会注意到我正在使用AttributeRouting。没有其他方法可以使用此操作的名称。

然而 - 这是我的位置课程:

    public class Location : ILocation
    {
       public DbGeography Coordinates { get; set; }

       public double Latitude { get; set; }

       public double Longitude { get; set; }
    }

这里没什么特别的(界面定义了所有这些属性)。

如果我正在访问控制器操作(实际使用powershell)并传递类似的内容:

http://localhost:2000/Feed?latitude=23.1&longitude=37

everthing工作正常,但如果我正在使用

http://localhost:2000/Feed

location参数是非null(它是一个带有默认值的新位置),这是我想要的行为:(。

有谁知道为什么会这样?

提前致谢

4 个答案:

答案 0 :(得分:7)

MVC模型绑定器已经接管。我最初发布的内容适用于不通过模型绑定器的实例。但是,based on other answers on SO和我自己的快速测试,看起来viewmodel参数永远不会为null,因为绑定器的工作方式和属性与表单值绑定。

在你的实例中,我会检查纬度和经度是否都为空,以查看是否有任何传递。这意味着您需要在ViewModel

上使它们可为空
public class Location : ILocation
    {
       public DbGeography Coordinates { get; set; }

       public double? Latitude { get; set; }

       public double? Longitude { get; set; }
    }

更新了控制器代码

if (location.Latitude == null && location.Longitude == null)
    {
        // init location or smth
    }

答案 1 :(得分:4)

ModelBinder创建对象的新实例,因此您有两个选项:

在'必需属性'上设置[Required] DataAnnotation并将其标记为可为空,然后检查ModelState.IsValid(推荐)

使纬度和经度可以为double?,您可以查看Latitude.HasValue && Longitude.HasValue

更新:

public class Location : ILocation
    {
       public DbGeography Coordinates { get; set; }

       public double? Latitude { get; set; }

       public double? Longitude { get; set; }
    }

public class LocationGetFeedsViewModel : LocationGetFeedsBinderModel {
       // change coordinates to string because maybe that's easier to handle on the view.
       public string Coordinates { get; set; }
       // added to sum to the example
       public IEnumerable<SelectListItem> Zones { get; set; } 
}

public class LocationGetFeedsBinderModel {
       [Required]
       public double? Latitude { get; set; }
       [Required]
       public double? Longitude { get; set; }
}

<强>控制器:

public ActionResult GetFeeds(LocationGetFeedsBinderModel location) {
    if (!ModelState.IsValid)
        // redirect or display some error 
    return new EmptyResult();
}

答案 2 :(得分:1)

默认模型绑定器将始终实例化一个复杂对象,因此它将永远不会为null,并且将跳过任何可选的赋值。

应用于您的系统的此行为的最终结果将是您必须检测默认构造函数的使用。用反射或隐式检查无法做到这一点。

必须明确地完成。

可以通过在默认构造函数中设置类中的标志来实现,通过使用Bart建议的数据注释,通过使用属性的自定义get和set方法,在接受的答案中建议使用可为空的属性,或者其他各种方式。

答案 3 :(得分:0)

我一直在使用angularjs测试 发布 数据。

我发现如果强制某个值为 null 而不是未定义,则ModelBinder不会实例化复杂对象。

if (!location)
    location = null;

$http({ method: "POST", url: "/Location/Create", data: { location } })