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
我正在从事 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