关于复杂类型的模型绑定的Web API + MVC 4

时间:2012-04-03 21:44:52

标签: asp.net-mvc-4 asp.net-web-api entity-framework-4.1

我有以下课程:

public class State
{
    public long Id                    { get; set; }
    public string Name                { get; set; }
    public string Abbreviation        { get; set; }

    // Navigation Properties
    public virtual Country Country    { get; set; }
}

public class School
{
    public long Id                    { get; set; }
    public string Name                { get; set; }
    public string Abbreviation        { get; set; }

    // Navigation Properties
    public virtual State State        { get; set; }
}

以及我的SQL Server中的以下数据

| School|             |               |
|  Id   | Name        |    State      |
|  1    | UCLA        |      1        |
+-------+-------------+---------------+
| State |             |               |
|  Id   | Name        | Abbreviation  |
|  1    | California  |      CA       |

我正在尝试使用Web API创建一个使用HTTP POST动词创建学校实例的Rest控制器。

public HttpResponseMessage<School> Post( School school )
{
    SchoolService.CreateSchool( school );
    var response = new HttpResponseMessage<School>( school, HttpStatusCode.Created );
    string uri = Url.Route( null, new { id = school.Id } );

    response.Headers.Location = new Uri( Request.RequestUri, uri );
    return response;
}

Web API从我的Web表单中正确绑定了我的School类的Name和Abbreviation属性,并在控制器中调用POST方法,但它不知道如何处理State类。我不太清楚如何设置它。我希望有一个绑定到State类的下拉列表,当我提交学校的创建时,我现有数据中的正确状态将被分配给新的学校实例。

2 个答案:

答案 0 :(得分:1)

首先,您的域模型设计有点粗糙。您的School表格应该有一个FKState表,您也应该在POCO课程中使用它:

public class School
{
    public long Id                    { get; set; }
    public long StateId               { get; set; }
    public string Name                { get; set; }
    public string Abbreviation        { get; set; }

    // Navigation Properties
    public virtual State State        { get; set; }
}

然后你应该有一个类似于下面的表单字段:

<select id="StateId" name="StateId">
    <option value="">Select a State</option>
    <option value="310">CA</option>
    <option value="311">NY</option>
</select>

答案 1 :(得分:0)

在我目前的项目中,我使用以下方法取得了类似的成果:

我有一个Device类(POCO)和一个DeviceCommand类(POCO)。设备可以有很多命令,每个命令只有一个设备。

我没有打扰ViewModel,POCO类在图层之间使用。

public class Device
{
    [Key]
    public int ID { get; set; }

    public int DeviceID { get; set; }

    public bool IsActive { get; set; }

    // Navigational properties
    public ICollection<DeviceCommand> CommandList { get; set; }
}

public class DeviceCommand
{
    public int Id { get; set; }

    public string CommandText { get; set; }
    public string CommandId { get; set; }

    // Navigational properties
    public int DeviceId { get; set; }
    public Device Device { get; set; }
}

在我的DbContext派生类中,我有以下代码:

    protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
    {         
        modelBuilder.Entity<DeviceCommand>()
            .HasRequired(d => d.Device)
            .WithMany(l => l.CommandList)
            .HasForeignKey(b => b.DeviceId)
            .WillCascadeOnDelete();
    }

IMO您必须使用注释或流畅的API设置外键关系。

如果POST方法中的参数没有属性,那么决定完全取决于参数的.NET类型。“简单类型”使用模型绑定。复杂类型使用格式化程序。

请参阅此链接以更好地了解web api绑定:

http://blogs.msdn.com/b/jmstall/archive/2012/04/16/how-webapi-does-parameter-binding.aspx

希望这有帮助。