Moortiii

Controller Example

Feb 24th, 2019
211
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 2.58 KB | None | 0 0
  1. ~/Models/BlogPost.cs:
  2.  
  3. public class BlogPost
  4. {
  5.     public int BlogPostID { get; set; }
  6.     public string Title { get; set; }
  7.     public string Content { get; set; }
  8.     public DateTime LastEdited { get; set; }
  9.     public ApplicationUser Author { get; set; }
  10. }
  11.  
  12. ~/Models/ApplicationUser.cs
  13.  
  14. public class ApplicationUser : IdentityUser
  15. {
  16.     public string Nickname;
  17.     public int Age;
  18. }
  19.  
  20. ~/Controllers/BlogController.cs:
  21.  
  22. private readonly ApplicationDbContext _context;
  23.  
  24. public async Task<IActionResult> Edit(int id, [Bind("BlogPostID, Title, Content")] BlogPost post)
  25. {
  26.     var author = _context.BlogPosts
  27.                     .Include(entry => entry.Author)
  28.                     .AsNoTracking()
  29.                     .FirstOrDefaultAsync(entry => entry.BlogPostId == id)
  30.                     .Result
  31.                     .Author;
  32.    
  33.     // Users should only be able to edit their own posts
  34.     if(author.Id != User.Id)
  35.     {
  36.         return RedirectToAction(nameof(Index));
  37.     }
  38.  
  39.     // Do some operations like updating when the post was edited
  40.     post.LastEdited = DateTime.Now;
  41.  
  42.     _context.Update(post);
  43.     await _context.SaveChangesAsync();
  44. }
  45.  
  46. // But what if we have abstracted retrieving posts to a service?
  47.  
  48. ~/Services/BlogPostService.cs:
  49.  
  50. private readonly ApplicationDbContext _context;
  51.  
  52. public async Task<BlogPost> GetBlogPostAsync(int id)
  53. {
  54.     var post = _context.BlogPosts
  55.                     .Include(entry => entry.Author)
  56.                     .FirstOrDefaultAsync(entry => entry.BlogPostId == id)
  57.                     .Result;
  58.  
  59.     // Verify that the post exists etc. here
  60.  
  61.     return post;
  62. }
  63.  
  64. // Then we get the following problem in the controller:
  65.  
  66. ~/Controllers/BlogController.cs:
  67.  
  68. private readonly IBlogPostService _blogPostService;
  69.  
  70. public async Task<IActionResult> Edit(int id, [Bind("BlogPostID, Title, Content")] BlogPost post)
  71. {
  72.     // This throws an error because there are now two instances tracking the same Primary Key { BlogPostID }
  73.     var author = _blogPostService.GetBlogPostAsync(id).Result.Author;
  74.    
  75.     // Users should only be able to edit their own posts
  76.     if(author.Id != User.Id)
  77.     {
  78.         return RedirectToAction(nameof(Index));
  79.     }
  80.  
  81.     // Do some operations like updating when the post was edited
  82.     post.LastEdited = DateTime.Now;
  83.  
  84.     _context.Update(post);
  85.     await _context.SaveChangesAsync();
  86. }
  87.  
  88. // If I modify the service class to use .AsNoTracking() when grabbing the post it could cause issues in situations where I DO want to track the changes.
  89.  
  90. // I could always have a function GetBlogPostAsyncAsNoTracking(int id); but that seems excessive and would cause redundant code. Furthermore, using an optional boolean argument to the GetBlogPostAsync(int id, bool? AsNoTracking); could work, but seems like a bad idea as well.
Advertisement
Add Comment
Please, Sign In to add comment