【发布时间】:2014-12-10 10:11:47
【问题描述】:
我正在使用 EF 6 和 MVC 5 开发博客引擎。
我决定不使用存储库模式或 UoW,因为它已经在框架级别的 EF 6 中实现。
解决方案包含以下层。
DataModels 层:它有简单的 POCO,它们是自动生成的和一个 dbContext。
public partial class Article
{
public int Id { get; set; }
public string Slug { get; set; }
public string Title { get; set; }
public string PostBody { get; set; }
public System.DateTime CreatedOn { get; set; }
public bool IsPublished { get; set; }
public string Author { get; set; }
}
服务层:
public interface IBlogEngine
{
List<Article> GetFrontPageBlogPosts();
void SaveArticle(Article article);
List<Article> GetArticlesByStatus(string isPublished);
Article GetBySlug(string slug);
Article GetById(int id);
bool Exists(string slugUrl);
void Delete(int id);
}
IBlogEngine 实现。为简洁起见,省略了一些方法实现。
public class BlogEngine : IBlogEngine
{
private readonly dbContext _context;
public BlogEngine(DbContext context)
{
_context = context;
}
public void SaveArticle(Article article)
{
if (article.Id == 0)
{
_context.Articles.Add(article);
}
else
{
_context.Entry(article).State = EntityState.Modified;
}
_context.SaveChanges();
}
public Article GetBySlug(string slug)
{
return _context.Articles.SingleOrDefault(x => x.Slug == slug.Trim());
}
}
界面层
public class ArticleController : Controller
{
private readonly IBlogEngine _engine;
public ArticleController(IBlogEngine engine)
{
_engine = engine;
}
[HttpGet]
public ActionResult Edit(string slug)
{
if (string.IsNullOrWhiteSpace(slug))
{
return HttpNotFound();
}
var article = _engine.GetBySlug(slug);
if (article == null)
{
return HttpNotFound();
}
var model = new EditViewModel { Id = article.Id, Slug = article.Slug,
Title = article.Title, PostBody = article.PostBody, IsPublished = true };
return View("Create", model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(EditViewModel blogPost)
{
if (!ModelState.IsValid)
{
return View("Create", blogPost);
}
// Get Article by Id
var article = _engine.GetById(blogPost.Id);
if (article == null)
{
return HttpNotFound();
}
// Update it
article.Id = blogPost.Id;
article.Title = blogPost.Title.Trim();
article.Slug = blogPost.Slug.ToUrlSlug();
article.PostBody = blogPost.PostBody;
article.CreatedOn = DateTime.UtcNow;
article.IsPublished = blogPost.IsPublished;
article.Author = User.Identity.Name;
// Save it
_engine.SaveArticle(article);
return RedirectToAction("Create", "Article");
}
}
问题 考虑这样一个场景,用户完成了对旧博客文章/文章的编辑并点击提交按钮来更新他的博客文章/文章。
我的 HTTP POST 编辑操作太胖了吗?我觉得控制器在这里做的事情也很可能。
从数据库中获取现有文章
用 ViewModel 值更新它
从服务层调用
SaveArticle方法。
我怎样才能让这个控制器节食?
Service Layer 方法 SaveArticle 不应该完成从 Db 检索文章并使用新值更新它并调用 SaveChanges 方法的工作吗?
如果上述陈述为真,我如何将 ViewModel 传递给 ServiceLayer 方法?允许 ViewModel 泄漏到 Service 层不是一个糟糕的决定吗?
我该如何处理?我很困惑,需要一些帮助。
【问题讨论】:
-
理论上您应该使用专用模型回发到您的控制器,而不是回发整个 ViewModel。使用专用模型,将该模型提供给存储库/服务层以执行其操作确实是正确的。
-
我将整个 ViewModel 发布到控制器操作(HTTP POST),因为它是必需的,因为我不知道用户更改了哪些字段。你的意思是我应该在 HTTP POST 操作方法中使用 Article 而不是 EditViewModel 吗?
-
对我来说看起来不错,并且正在做控制器 POST 方法应该做的事情。接受视图模型,验证它,映射到域模型,保存并重定向。
-
@StephenMuecke ServiceLayaer 方法可以返回 DTO 而不是 Domain 对象吗?因为,在某些方法中,我返回整个域对象,但在控制器级别,我只需要很少的属性。
-
如果您使用视图模型仅显示/编辑您需要的数据,这不会有任何问题
标签: asp.net-mvc entity-framework design-patterns service-layer