I'm working on WebApi project and I have 2 entities in my domain:
Street
我正在开发WebApi项目,我的域名中有2个实体:Street
public class Street
{
public int ID { get; set; }
public string Name { get; set; }
public int StreetTypeID { get; set; }
public virtual StreetType StreetType { get; set; }
}
and StreetType:
public class StreetType
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Street> Streets { get; set; }
}
I use FluenApi to map these entities:
我使用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");
}
}
and the similar for Street entity.
Now I get JSON:
和街道实体类似。现在我得到JSON:
{
"id":1,
"name":"Street1",
"streettypeid":3
}
How can I get the JSON like:
如何获得JSON:
{
"id":1,
"name":"Street1",
"streettypeid":
{
"id":3,
"name":"Type3"
}
}
Or some similar structure. How can I accomplish this in .NET?
或者一些类似的结构。我怎样才能在.NET中实现这一目标?
My Controller:
StreetController : BaseApiController<Street>
and
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;
}
}
2 个解决方案
#1
2
To preserve object references in JSON, add the following code to Application_Start method in the Global.asax file:
要保留JSON中的对象引用,请将以下代码添加到Global.asax文件中的Application_Start方法:
var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling =
Newtonsoft.Json.PreserveReferencesHandling.All;
For more datail please read this article.
有关更多数据,请阅读本文。
Another way is try to use OData in your webapi. You have to install the OData Packages:
另一种方法是尝试在webapi中使用OData。您必须安装OData包:
Install-Package Microsoft.AspNet.Odata
Then you'll able yo use $expand
that causes related entities to be included inline in the response.
You can leave all as is, but I think it will properly to add IgnoreDataMember
(do not forget add using System.Runtime.Serialization
;)
然后你就可以使用$ expand来导致相关实体被包含在响应内联中。您可以按原样保留所有内容,但我认为可以正确添加IgnoreDataMember(不要忘记使用System.Runtime.Serialization添加;)
public class StreetType
{
public int ID { get; set; }
public string Name { get; set; }
[IgnoreDataMember]
public virtual ICollection<Street> Streets { get; set; }
}
Also need to add attribute to you Get
method:
还需要为你添加属性Get方法:
[EnableQuery]
public virtual IQueryable<T> Get()
After that you can create http-request like:
之后,您可以创建http请求,如:
http://blablabla/Street?$expand=StreetType
and get all Streets
with their StreetType
并使用他们的StreetType获取所有Streets
#2
1
You need to create a view model to return that has the included entity.
您需要创建一个视图模型以返回包含实体的视图模型。
Edit: here's a complete api controller method including proposed route.
编辑:这是一个完整的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);
}
#1
2
To preserve object references in JSON, add the following code to Application_Start method in the Global.asax file:
要保留JSON中的对象引用,请将以下代码添加到Global.asax文件中的Application_Start方法:
var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling =
Newtonsoft.Json.PreserveReferencesHandling.All;
For more datail please read this article.
有关更多数据,请阅读本文。
Another way is try to use OData in your webapi. You have to install the OData Packages:
另一种方法是尝试在webapi中使用OData。您必须安装OData包:
Install-Package Microsoft.AspNet.Odata
Then you'll able yo use $expand
that causes related entities to be included inline in the response.
You can leave all as is, but I think it will properly to add IgnoreDataMember
(do not forget add using System.Runtime.Serialization
;)
然后你就可以使用$ expand来导致相关实体被包含在响应内联中。您可以按原样保留所有内容,但我认为可以正确添加IgnoreDataMember(不要忘记使用System.Runtime.Serialization添加;)
public class StreetType
{
public int ID { get; set; }
public string Name { get; set; }
[IgnoreDataMember]
public virtual ICollection<Street> Streets { get; set; }
}
Also need to add attribute to you Get
method:
还需要为你添加属性Get方法:
[EnableQuery]
public virtual IQueryable<T> Get()
After that you can create http-request like:
之后,您可以创建http请求,如:
http://blablabla/Street?$expand=StreetType
and get all Streets
with their StreetType
并使用他们的StreetType获取所有Streets
#2
1
You need to create a view model to return that has the included entity.
您需要创建一个视图模型以返回包含实体的视图模型。
Edit: here's a complete api controller method including proposed route.
编辑:这是一个完整的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);
}