Asp.net mvc 4 Web API+;关于复杂类型的模型绑定的MVC4

Asp.net mvc 4 Web API+;关于复杂类型的模型绑定的MVC4,asp.net-mvc-4,asp.net-web-api,entity-framework-4.1,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

我有以下课程:

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       |
我正在尝试创建一个Rest控制器,它使用HTTP POST谓词和Web API创建一个school实例

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;
}
公共HttpResponseMessage Post(学校)
{
学校服务。创建学校(学校);
var响应=新的HttpResponseMessage(学校,HttpStatusCode.Created);
字符串uri=Url.Route(null,新{id=school.id});
response.Headers.Location=新Uri(Request.RequestUri,Uri);
返回响应;
}

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

首先,您的域模型设计有点粗糙。你的
School
表应该有一个
FK
to
State
表,你的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>

选择一个状态
加利福尼亚州
纽约

首先,您的域模型设计有点粗糙。你的
School
表应该有一个
FK
to
State
表,你的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>

选择一个状态
加利福尼亚州
纽约

在我当前的项目中,我使用以下方法实现了类似的目标:

我有一个设备类(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; }
}
在我的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();
    }
protectedoverride void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{         
modelBuilder.Entity()
.has必需(d=>d.Device)
.WithMany(l=>l.CommandList)
.HasForeignKey(b=>b.DeviceId)
.WillCascadeOnDelete();
}
在我看来,您必须使用注释或fluent API设置外键关系

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

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


希望这能有所帮助。

在我当前的项目中,我使用以下方法实现了类似的效果:

我有一个设备类(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; }
}
在我的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();
    }
protectedoverride void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{         
modelBuilder.Entity()
.has必需(d=>d.Device)
.WithMany(l=>l.CommandList)
.HasForeignKey(b=>b.DeviceId)
.WillCascadeOnDelete();
}
在我看来,您必须使用注释或fluent API设置外键关系

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

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


希望这有帮助。

您如何提交
存储
类的值?你能发布HTTP请求的详细信息(标题、表单字段和值等)吗?我也有同样的问题;我在一篇文章中对一个复杂类型进行XML反序列化,它尝试使用ModelBinder而不是默认的XmlMediaTypeFormatter。有人提到JSON可以很好地实现这一点——您使用的是XML还是JSON序列化?如何提交
Store
class的值?你能发布HTTP请求的详细信息(标题、表单字段和值等)吗?我也有同样的问题;我在一篇文章中对一个复杂类型进行XML反序列化,它尝试使用ModelBinder而不是默认的XmlMediaTypeFormatter。有人提到JSON可以很好地实现这一点——您是使用XML还是JSON序列化?嗨,Tugberk,在我之前的迭代中,我会有一个包含FK的学校视图模型。自从引入Web API以来,我想尝试在不使用FKs和不使用viewmodel类的情况下实现这一点,希望有某种方法来绑定复杂类型,例如本例中的状态。我想我的问题是,是否可以不使用FKs以这种方式实现它,如果可以,如何设置Post方法以及如何提交state的值。如果不可能的话,我可能不得不以FK/viewmodel的方式完成。嗨,Tugberk,在我之前的迭代中,我会有一个包含FK的学校视图模型。自从引入Web API以来,我想尝试在不使用FKs和不使用viewmodel类的情况下实现这一点,希望有某种方法来绑定复杂类型,例如本例中的状态。我想我的问题是,是否可以不使用FKs以这种方式实现它,如果可以,如何设置Post方法以及如何提交state的值。如果不可能的话,我可能不得不用FK/viewmodel的方式来完成。