Lý do viết bài này rất đơn giản: mình bỏ cả buổi chiều ngồi cố gắng return danh sách sản phẩm dạng JSON từ controller về mà toàn lỗi 500 Internal Server Error.
Đầu tiên đổ tại lỗi IIS Express, khởi động đi khởi động lại, build đi build lại mà vẫn lỗi :((. Search hoài cả buổi thì cuối cùng cũng tìm ra vấn đề là thằng model sinh tự động từ DB ra nó có kết nối khóa ngoại nên không Serialize về dạng JSON được (thảo nào toàn return 500 :(( ). Cách fix là tạo ra 1 model khác (VD: ProductViewModel), coppy toàn bộ bên model sinh tự động sang trừ thằng nào có chữ “virual” ra (khóa ngoại).
Định note lại mà nhớ ra note xong không nhớ note để đâu cộng với blog để lâu không post bài nên quyết định viết 1 bài 😀
Đoạn dưới đây mình viết xàm thôi, nên đọc nửa chừng thấy củ chuối thì bỏ đi :v. Quan trọng biết cách fix là được.
Nói qua về vấn đề của mình, mình có 2 cái model sinh tự động từ DB ra trông như này
Code model tự động sinh của nó trông như này
Mình muốn gửi 1 request ajax đến lấy ra danh sách các sản phẩm.
var name = $('#searchInput1').val(); $.ajax({ contentType: "application/json", dataType: 'json', data: {'name': name}, type: "GET", url: '/Home/SearchResult', success: function (response) { console.log(response); } });
Tay nhanh hơn não, mình liền viết ngay 1 phương thức bên trong HomeController:
// GET: Home/SearchResult/name [HttpGet] public JsonResult SearchResult(string name) { List<Product> list = db.Products.Where(x => x.ProductName.Contains(name)).ToList(); return Json(list, JsonRequestBehavior.AllowGet); }
Không ngờ gặp lỗi
Nhanh tay, mình cắm ngay 2 con debug ở chỗ list và return, hòng chén ngay con bug này.
Ơ, select ngon lành thế kia cơ mà, rõ ràng có 2 thằng product trong list, thế mà nó trả về 500 to tướng.
Và mình khắc phục như sau:
Tạo class ProductViewModel
public class ProductViewModel { public long ProductID { get; set; } public long CategoryID { get; set; } [Required(ErrorMessage = "Vui lòng nhập tên sản phẩm")] public string ProductName { get; set; } public string ProductDescription { get; set; } public string ProductNote { get; set; } }
Để ý thì thấy nó khác cái Product tự sinh ở chỗ bỏ hàm
public virtual Category Category { get; set; }
Đây là hàm kết nối đến bảng danh mục thông qua khóa ngoại CategoryID
Cuối cùng là sửa code trong HomeController
List<Product> list = db.Products.Where(x => x.ProductName.Contains(name)) .ToList(); List<ProductViewModel> viewList = new List<ProductViewModel>(); foreach (var product in list) { viewList.Add(new ProductViewModel() { ProductID = product.ProductID, CategoryID = product.CategoryID, ProductName = product.ProductName, ProductDescription = product.ProductDescription, ProductNote = product.ProductNote }); } return Json(viewList, JsonRequestBehavior.AllowGet);
Ngoài ra, khi update CSDL, nếu sử dụng trực tiếp model sinh sẵn, có thể gây lỗi.
Nếu sử dụng model riêng, thì có thể dùng tạm mấy bữa rồi fix sau cũng được =)))
Kết luận
Tránh sử dụng model sinh tự động =))
Pingback: Khác nhau giữa Entity Model và Business Object (BO) | minhphong306
I do кnow!? Mentioned Larry. ?I ɡuess he lіkes angels as a
result of he has tһem around all the time. Perhaps he and the angels play
household games like we do sometimes. Maybe they play Monopoly.?
This made Mommy chuckle really hard.
ThíchThích
Sorry. I don’t know what you said. I think you are auto bot. Right?
ThíchThích