title: ASP NET CORE MVC - Correct way to pass data from view to controller?
body: <p>I am learning ASP Net Core 2.2 MVC. I have read several articles regarding passing data from controller to view and vice-versa. At one point I wanted to pass more than 1 model to the view.</p>
  
  <p>Then I realized that I cannot, and have to use what is called a <code>View Model</code>. I came up with this:</p>
  
  <p><strong>My <code>Domain Models</code>:</strong></p>
  
  <p><strong><code>Blog.cs:</code></strong> </p>
  
  <p>A blog can have many categories, all the other properties are the usual <code>title</code>, <code>body</code> etc.</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.ComponentModel.DataAnnotations;
  using System.ComponentModel.DataAnnotations.Schema;
  
  namespace Blogspot.Datas.Models
  {
      public class Blog
      {
          [Key]
          public int id { get; set; }
  
          [Required]
          [DataType(DataType.Text)]
          public string title { get; set; }
  
          [Required]
          [DataType(DataType.Text)]
          public string body { get; set; }
  
          [DataType(DataType.DateTime)]
          public DateTime created_at { get; set; }
  
          [Column(TypeName = "boolean")]
          public bool comments { get; set; }
  
          public List&lt;Category&gt; categories { get; set; }
      }
  }
  </code></pre>
  
  <p><strong><code>Category.cs:</code></strong></p>
  
  <pre><code>using System;
  using System.ComponentModel.DataAnnotations;
  using System.ComponentModel.DataAnnotations.Schema;
  
  namespace Blogspot.Datas.Models
  {
      public class Category
      {
          [Key]
          public int id { get; set; }
          [Required]
          public string title { get; set; }
  
          public int blog_id { get; set; }
          [ForeignKey("blog_id")]
          public Blog blog { get; set; }
      }
  }
  </code></pre>
  
  <p>In one of my view - <code>Info.cshtml</code>, I want to show a <code>blog</code> with its <code>categories</code>. </p>
  
  <p><strong><code>InfoViewModel.cs:</code></strong></p>
  
  <pre><code>using System.Collections.Generic;
  using System.ComponentModel.DataAnnotations;
  using Blogspot.Datas.Models;
  
  namespace Blogspot.Datas.Models.Pages
  {
      public class InfoViewModel
      {
          public InfoViewModel()
          {
              this.categories = new List&lt;Category&gt;();
              this.category = new Category();
          }
          public int id { get; set; }
  
          [Required]
          public string title { get; set; }
  
          [Required]
          public string body { get; set; }
  
          [Required]
          public Category category { get; set; }
          public List&lt;Category&gt; categories { get; set; }
      }
  }
  </code></pre>
  
  <p><strong><code>Info.cshtml:</code></strong></p>
  
  <p>It shows the <code>title</code> and <code>body</code> of the blog, an its categories. I can also add a category (in the <code>modal form</code>).</p>
  
  <pre><code>@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
  
  
  @model Blogspot.Datas.Models.Pages.InfoViewModel
  
  
  &lt;section class="infos"&gt;
      &lt;form action="#"&gt;
          &lt;input type="hidden" asp-for="@Model.id"&gt;
  
          &lt;div class="form-group"&gt;
              &lt;label for="title"&gt;Title&lt;/label&gt;
              &lt;input class="form-control" type="text" asp-for="@Model.title"&gt;            
          &lt;/div&gt;
  
          &lt;div class="form-group"&gt;
              &lt;label for="body"&gt;Body&lt;/label&gt;
              &lt;input class="form-control" type="text" asp-for="@Model.body"&gt;
          &lt;/div&gt;
      &lt;/form&gt;
  
          &lt;div class="categories"&gt;
              &lt;h3&gt;Categories
                  &lt;button type="button" style="float: right" class="btn btn-primary add-category"&gt;Add category&lt;/button&gt;
              &lt;/h3&gt;
              @foreach (var c in @Model.categories)
              {
                  &lt;div class="cat"&gt;
                      &lt;p&gt;@c.title&lt;/p&gt;
                      &lt;form asp-route="deleteCategory" asp-route-id="@c.id"&gt;
                          &lt;button type="submit" class="btn btn-danger"&gt;Delete&lt;/button&gt;
                      &lt;/form&gt;
                      &lt;hr&gt;
                  &lt;/div&gt;
              } 
          &lt;/div&gt;
  &lt;/section&gt;
  
  &lt;div class="modal fade category" tabindex="-1" role="dialog"&gt;
    &lt;div class="modal-dialog" role="document"&gt;
      &lt;div class="modal-content"&gt;
        &lt;div class="modal-header"&gt;
          &lt;h5 class="modal-title"&gt;Modal title&lt;/h5&gt;
          &lt;button type="button" class="close" data-dismiss="modal" aria-label="Close"&gt;
            &lt;span aria-hidden="true"&gt;&amp;times;&lt;/span&gt;
          &lt;/button&gt;
        &lt;/div&gt;
        &lt;div class="modal-body"&gt;
          &lt;form asp-route="storeCategory" method="post" asp-anti-forgery="true"&gt;
              &lt;div class="form-group"&gt;
                  &lt;label asp-for="@Model.category.title"&gt;Title&lt;/label&gt;
                  &lt;input class="form-control" type="text" asp-for="@Model.category.title"&gt;
                  &lt;span class="text-danger" asp-validation-for="@Model.category.title"&gt;&lt;/span&gt;
              &lt;/div&gt;
              &lt;input type="hidden" asp-for="@Model.category.blog_id" value="@Model.id"&gt;
              &lt;input type="submit" value="Save category" class="btn btn-success"&gt;
          &lt;/form&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p>Now what has got me thinking is what would be the <strong>correct</strong> way of passing a parameter to the  <code>POST store function</code>?</p>
  
  <pre><code>[HttpPost("categories", Name="storeCategory")]
      [ExportModelState]
      public async Task&lt;IActionResult&gt; storeCategory(Category category)
      {
          if (ModelState.IsValid)
          {
              await _context.category.AddAsync(category);
              await _context.SaveChangesAsync();    
  
              TempData["success"] = true;
              TempData["message"] = "Category added succesfully!";
          }
  
          return RedirectToRoute("postDetails", new { id = category.blog_id });
  
      }
  </code></pre>
  
  <p>What I've done is pass in the <code>Category</code> Domain Model. I saw articles which said that it should be <code>View Model</code> that gets passed, because its not a good practice to pass around Domain Models. Now my function works perfectly, but in the instance I pass a View Model, like <code>storeCategory(InfoViewModel infoViewModel)</code> wouldn't the other properties <code>id, title, property, categories</code> be redundant? Because all I need for that function is a category object.</p>
  
  <p>Please enlightened me all of this patterns and conventions used.</p>
  
  <p>Thank you.</p>