Moortiii icon

Controller Example

Moortiii | PRO | 02/24/19 07:07:16 PM UTC | 0 ⭐ | 414 👁️ | Never ⏰ | []
C# |

2.58 KB

|

None

|

0 👍

/

0 👎

~/Models/BlogPost.cs:
 
public class BlogPost
{
    public int BlogPostID { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public DateTime LastEdited { get; set; }
    public ApplicationUser Author { get; set; }
}
 
~/Models/ApplicationUser.cs
 
public class ApplicationUser : IdentityUser
{
    public string Nickname;
    public int Age;
}
 
~/Controllers/BlogController.cs:
 
private readonly ApplicationDbContext _context;
 
public async Task<IActionResult> Edit(int id, [Bind("BlogPostID, Title, Content")] BlogPost post)
{
    var author = _context.BlogPosts
                    .Include(entry => entry.Author)
                    .AsNoTracking()
                    .FirstOrDefaultAsync(entry => entry.BlogPostId == id)
                    .Result
                    .Author;
    
    // Users should only be able to edit their own posts
    if(author.Id != User.Id)
    {
        return RedirectToAction(nameof(Index));
    }
 
    // Do some operations like updating when the post was edited
    post.LastEdited = DateTime.Now;
 
    _context.Update(post);
    await _context.SaveChangesAsync();
}
 
// But what if we have abstracted retrieving posts to a service?
 
~/Services/BlogPostService.cs:
 
private readonly ApplicationDbContext _context;
 
public async Task<BlogPost> GetBlogPostAsync(int id)
{
    var post = _context.BlogPosts
                    .Include(entry => entry.Author)
                    .FirstOrDefaultAsync(entry => entry.BlogPostId == id)
                    .Result;
 
    // Verify that the post exists etc. here
 
    return post;
}
 
// Then we get the following problem in the controller:
 
~/Controllers/BlogController.cs:
 
private readonly IBlogPostService _blogPostService;
 
public async Task<IActionResult> Edit(int id, [Bind("BlogPostID, Title, Content")] BlogPost post)
{
    // This throws an error because there are now two instances tracking the same Primary Key { BlogPostID }
    var author = _blogPostService.GetBlogPostAsync(id).Result.Author;
    
    // Users should only be able to edit their own posts
    if(author.Id != User.Id)
    {
        return RedirectToAction(nameof(Index));
    }
 
    // Do some operations like updating when the post was edited
    post.LastEdited = DateTime.Now;
 
    _context.Update(post);
    await _context.SaveChangesAsync();
}
 
// 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.
 
// 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.

Comments