ASP.NET MVC HttpGet vs HttpPost

Problem:

I have a page that displays list of items. And user can filter the items by create date, title, etc. For example:

<h2>Blog List</h2>

@using (Html.BeginForm("List", "Blog"))
{
 @Html.EditorFor(m => m.Filter.CreateDate)
 @Html.EditorFor(m => m.Filter.Title)

 // Table ...

 <input type="submit" value="Submit"/>
}

The action looks something like this:

public ActionResult List(BlogListFilter filter)
{
  var filter = filter ?? new BlogListFilter();
  var model = new BlogListViewModel
  {
    Filter = filter,
    Blogs = _blogService.GetBlogsByFilter(filter)
  };

  return View(model);
}

It works well until i want to add a pager compent for the table because the list of blogs is too large.

@using (Html.BeginForm("List", "Blog"))
{
 @Html.EditorFor(m => m.Filter.CreateDate)
 @Html.EditorFor(m => m.Filter.Title)

 // Table ...

 @Html.PagerFor(m => m.Paging)
 <input type="submit" value="Submit"/>
}

The problem occurs when clicking on the page number to jump to another page. The filter turn out be not working anymore in this case.

public ActionResult List(BlogListFilter filter, int page = 1)
{
  var filter = filter ?? new BlogListFilter();

  // ... create Paging information 
  // ... create paged list
  var model = new BlogListViewModel
  {
    Filter = filter,
    Blogs = pagedBlogList
  };

  return View(model);
}

When I debug it, i found that the filter parameter was null on List action.

After half hour research and comparing with other working example, i found the solution to fixing it was adding HttpGet attribute on List action and FormMethod.Get to form.

Why?

First, i didn’t explictly specify HTTP request method, then the default one is HTTP POST. This can be proved in ASP.NET MVC source code:

20160521153548

 

Second, what’s the accutally difference between HttpGet and HttpPost?  There is a article related to this topic on W3CShool.

The key difference is that when sending data, the GET method adds the data to the URL. In this case, the filter data has been added into URL. You can see it clearly in the Browser’s address bar.

http://localhost:49182/Blog/List?Filter.CreateDate=2016-01-01+00%3A00%3A00&Filter.Title=&page=2

So when clicking page number, the pager just gets current URL and add “page” parameter to that and send the complete URL to server. So the action can still receive the current filter data.

If using HttpPost, then the URL only contains page number data.

http://localhost:49182/Blog/List?page=2

 

Leave a comment