在我的ASP.NET MVC应用程序中,我有很多返回JSON的动作 在这些JSON中,重复了一些子结构。
例如
等...
这里我展示(1):
public JsonResult Members(long musicBandId)
{
MusicBand b = db.MusicBands.SingleOrDefault(b => b.MusicBandId == musicBandId);
if (b == null)
return null;
return Json(new
{
error = false,
message = "",
persons = from m in b.Members select new
{
musicianId = p.MusicianId,
name = m.Name,
instrument = new
{
instrumentId = m.instrument.InstrumentId,
model = m.instrument.Model
}
}
}, JsonRequestBehavior.AllowGet);
}
在这里我展示(2):
public JsonResult All(int page, int pageSize)
{
var musicians = db.Musicians;
var pageOfMusicians = musicians.Skip((page-1) * pageSize).Take(pageSize);
return Json(new
{
error = false,
message = "",
musiciansCount = musicians.Count(),
page = page,
pageSize = pageSize
musicians = from m in pageOfMusicians select new
{
musicianId = m.MusicianId,
name = m.Name,
instrument = new
{
instrumentId = m.instrument.InstrumentId,
model = m.instrument.Model
}
}
}, JsonRequestBehavior.AllowGet);
}
这有几个问题:
如果我想更改JSON格式,我必须在每个动作中更改它!
例如:如果我想改变" name" to" fullname",我必须在Members()和All()中更改它
很多"复制粘贴":如果我正在创建一个新的动作,结构中的某个地方返回一个音乐家,我需要复制并粘贴代表该部分的代码片段音乐家
{
musicianId = p.MusicianId,
name = p.Name,
instrument = new
{
instrumentId = instrument.InstrumentId,
model = instrument.Model
}
}
代码太大
这个问题有什么解决方案?
如果你提出一个框架,请告诉我以前的查询如何看待该框架
注意我在我的示例中总是使用Linq到实体,并且由于性能问题,我希望保持这样。我知道,对于Linq-to-objects,我可以这样:
from m in pageOfMusicians.ToList() select m.GetDTO()
使用GetDTO()
某些可以使用Linq-to-Objects运行的方法
但话说回来,我想坚持Linq-to-Entities
答案 0 :(得分:2)
备选方案1
如果您不担心使用与常规类型C#代码混合的动态,您可以制作一个实用方法,如...
public static dynamic PrepareForMusiciansView(IQuerable<Musician> musicians)
{
return musicians.Select(m => new
{
musicianId = m.MusicianId,
name = m.Name,
instrument = new
{
instrumentId = m.instrument.InstrumentId,
model = m.instrument.Model
}
}
}
......然后......
return Json(new
{
error = false,
message = "",
musiciansCount = musicians.Count(),
page = page,
pageSize = pageSize
musicians = Util.PrepareForMusiciansView(pageOfMusicians)
}, JsonRequestBehavior.AllowGet);
方法名称应明确反映其在申请方面的目的。也许您希望更多地关注序列化功能并使用类似PrepareForJson
的名称。此外,它应符合您的编码标准。如果没有使用别的动力,我会避免使用它。
备选方案2
使用AutoMapper(可通过NuGet获得)。
使用AutoMapper,您通常拥有Musician
和Instrument
的DTO类,具有您要在视图中公开的属性。如果这些属性与源类中的属性具有相同的名称,则AutoMapper将按名称约定匹配它们。
使用AutoMapper始终涉及定义映射和执行映射。应用程序启动时应定义映射一次。它看起来像......
Mapper.CreateMap<Musician, MusicianDto>();
Mapper.CreateMap<Instrument, InstrumentDto>();
执行映射有多种方法,但在使用IQueryable
时,首选方法是
musicians = pageOfMusicians.Project().To<MusicianDto>()
这会将IQueryable<Musician>
投射到IQueryable<MusicianDto>
,包括嵌套的Instrument
(如果DTO具有该名称的属性)。
这是我可以想到的两个可行的替代方案,可以将笨拙的new {}
语句减少为可重用的单行语句。这取决于您的应用程序和编码风格,您更喜欢哪种替代方案。