This post is part of a series of blog posts about bad codes or bad practices I’ve come across. Note that this is my personal opinion and some of the things I mention could be debatable.
Post 1: Code review, why it matters
Post 2: Not including JS, CSS and static content files in project
Post 3: Let’s just not unit test our code
Post 4: Don’t pass dependencies into helper methods
Post 5: Inline SQL query statement in static helper class
Post 6: Single model for both GET and POST in controller
I’ve seen in previous project where developers use the same model for both GET and POST endpoints because they did not want to have to create separate models for those. There are a few issues with that approach
- You allow users to over post to your endpoint (others might call it mass assignment). This can be a potential security risk as users might post values that bind to properties you don’t allow to.
- The POST model usually does not care about those for display only properties i.e. list of items to populate drop down lists.
- You can’t tell which properties are used.
There are a few ways to avoid this.
Using the Bind attribute
The Bind attribute allows you to either include or exclude properties when binding model.
Let’s say we have a model like this
public class Article { public Guid Id { get; set; } public string Name { get; set; } public string Body { get; set; } public bool IsDeleted { get; set; } public string AuthorName { get; set; } }
You have a POST endpoint that you only want to include properties Name and Body
[HttpPost] public IActionResult Edit([Bind(Include = "Id, Name, Body")] Article article) { // logic goes here }
Or you can exclude certain properties
[HttpPost] public IActionResult Edit([Bind(Exclude = "IsDeleted, AuthorName")] Article article) { // logic goes here }
Separate models for GET and POST
This is my favourite approach. So for the GET I would have a view model and for a POST there would be a submit model
public class ArticleViewModel { public Guid Id { get; set; } public string Name { get; set; } public string Body { get; set; } public bool IsDeleted { get; set; } public string AuthorName { get; set; } }
public class ArticleEditSubmitModel { public Guid Id { get; set; } public string Name { get; set; } public string Body { get; set; } }
[HttpGet] public IActionResult View(ArticleViewModel article) { // logic goes here } [HttpPost] public IActionResult Edit(ArticleEditSubmitModel article) { // logic goes here }