本博客爲做者平常工做遇到的一些問題集合,但願能給熱愛編程的初學者一些知識。編程
基於在應用EF實體類,若是存在導航屬性,則return Json(List<Entity> list,JsonRequestBehavior.AllowGet)時會遇到無限循環致使報錯的問題,因此但願有辦法解決此問題。json
解決思路1:app
1.新增多一個EF模板,把其導航屬性去除。ide
在.tt模板中,把類名加Model,與原來的類名區分開來。oop
<#=codeStringGenerator.EntityClassOpening(entity)+"Model"#>
<# foreach (var navigationProperty in navigationProperties) { #> <#=codeStringGenerator.NavigationProperty(navigationProperty)#> <# } #>
2.利用一個方法把List<Entity>批量轉換成List<EntityModel>。性能
public class Mapper<T,K> { /// <summary> /// 把List<T>轉換成List<K> /// </summary> /// <param name="listT"></param> /// <param name="model">默認new Model()</param> /// <returns></returns> public static List<K> MapObjectList(List<T> listT, K model) { BinaryFormatter bf = new BinaryFormatter(); MemoryStream ms = new MemoryStream(); bf.Serialize(ms, model); //複製到流中 List<K> listK = new List<K>(); foreach (T t in listT) { ms.Position = 0; K k = (K)(bf.Deserialize(ms)); ObjectMapperManager.DefaultInstance.GetMapper<T, K>().Map(t, k); listK.Add(k); } return listK; }
3.可用return Json(List<EntityModel> list,JsonRequestBehavior.AllowGet)學習
這樣把其導航屬性去掉,前臺就不會出現無線循環的報錯了。this
EmitMapper.ObjectMapperManager 能夠在nuget裏面找到,挺好用的一個類,是用來把EntityA轉換成EntityB,把兩個實體相同屬性的名稱spa
對應賦值。.net
可是,這樣作效率彷佛不高,並且還比較麻煩。因而再找找有沒有更便捷的方法,畢竟每次都這樣又裝箱又拆箱,性能損耗也是很多。因而有了解決思路2
解決思路2:
直接利用方法去除類中的導航屬性!!
寫一個MyJsonResult類
public class MyJsonResult : JsonResult { public JsonSerializerSettings Settings { get; private set; } public MyJsonResult() { Settings = new JsonSerializerSettings { //這句是解決問題的關鍵,也就是json.net官方給出的解決配置選項. ReferenceLoopHandling = ReferenceLoopHandling.Ignore }; } public override void ExecuteResult(ControllerContext context) { if (context == null) throw new ArgumentNullException("context"); if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet && string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) throw new InvalidOperationException("JSON GET is not allowed"); HttpResponseBase response = context.HttpContext.Response; response.ContentType = string.IsNullOrEmpty(this.ContentType) ? "application/json" : this.ContentType; if (this.ContentEncoding != null) response.ContentEncoding = this.ContentEncoding; if (this.Data == null) return; var scriptSerializer = JsonSerializer.Create(this.Settings); using (var sw = new StringWriter()) { scriptSerializer.Serialize(sw, this.Data); response.Write(sw.ToString()); } } }
而後,在BaseController裏重寫Json方法
public class BaseController : Controller { protected override JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior) { return new MyJsonResult { Data = data, ContentType = contentType, ContentEncoding = contentEncoding, JsonRequestBehavior = behavior }; } }
若是哪位大神有更好的解決辦法,請賜教。