ASP.NET WebApi JSON 带有外键的响应和实体

ASP.NET WebApi JSON Response and Entities with foreign key

我正在从事 WebApi 项目,我的域中有 2 个实体:
街道

public class Street
{
  public int ID { get; set; }
  public string Name { get; set; }
  public int StreetTypeID { get; set; }
  public virtual StreetType StreetType { get; set; }
}

和街道类型:

public class StreetType
{
  public int ID { get; set; }
  public string Name { get; set; }
  public virtual ICollection<Street> Streets { get; set; }
}

我使用 FluenApi 映射这些实体:

public class StreetTypeMap : EntityTypeConfiguration<StreetType>
{
  public StreetTypeMap()
  {
     HasKey(t => t.ID);
     Property(t => t.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
     Property(t => t.Name).IsRequired().HasMaxLength(50);
     HasMany(a => a.Streets).WithRequired(p => p.StreetType).HasForeignKey(p => p.StreetTypeID);
     ToTable("StreetType");
   }
 }

街道实体也类似。
现在我得到 JSON:

{
  "id":1,
  "name":"Street1",
  "streettypeid":3
}

如何获得 JSON 之类的:

{
  "id":1,
  "name":"Street1",
  "streettypeid":
   {
    "id":3,
    "name":"Type3"
   }
}

或者一些类似的结构。我如何在 .NET 中完成此操作?

我的控制器:

StreetController : BaseApiController<Street>

    public class BaseApiController<T> : ApiController where T : BaseEntity
    {
        protected UnitOfWork unitOfWork = new UnitOfWork();

        protected IRepository<T> repository;

        public BaseApiController()
        {
            repository = unitOfWork.EFRepository<T>();
        }
        public virtual IQueryable<T> Get()
        {
          var entity = repository.Table;

          if (entity == null)
          {
              throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NoContent));
          }
          return entity;
      }

}

您需要为 return 创建一个包含实体的视图模型。

编辑:这是一个完整的 api 控制器方法,包括建议的路线。

    [HttpGet, Route("/api/streets/{id:int:min(1)}")]
    public IHttpActionResult GetYourJsonData(int id)
    {
        try
        {
            //from your unit of work class
            return uow.GetEntities<Street>(x => x.ID == id)
                .FirstOrDefault()
                .Select(viewModel => new {
                    ID = viewModel.ID,
                    Name = viewModel.Name,
                    StreetTypeID = viewModel.StreetType //consider renaming this to streeytype and not street type id
                });
        }
        catch(Exception)
        {
             return InternalServerError();
        }
    }



//Edit: in your repo class
public IEnumerable<T> GetEntities<T>(Func<T, bool> predicate) where T : class
{
    return yourContext.Set<T>().Where(predicate);
}

要保留 JSON 中的对象引用,请将以下代码添加到 Global.asax 文件中的 Application_Start 方法:

var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = 
    Newtonsoft.Json.PreserveReferencesHandling.All;

有关更多数据,请阅读 this 文章。

另一种方法是尝试在您的 webapi 中使用 OData。 您必须安装 OData 包:

Install-Package Microsoft.AspNet.Odata

然后您就可以使用 $expand 使相关实体内联包含在响应中。
你可以保持原样,但我认为添加 IgnoreDataMember 会很合适(不要忘记添加 using System.Runtime.Serialization;)

public class StreetType
{
  public int ID { get; set; }
  public string Name { get; set; }
  [IgnoreDataMember]
  public virtual ICollection<Street> Streets { get; set; }
}

还需要给你添加属性Get方法:

[EnableQuery]
public virtual IQueryable<T> Get()

之后你可以像这样创建 http 请求:

http://blablabla/Street?$expand=StreetType

并获得所有 Streets 及其 StreetType