How to return 404 page in ASP .NET MVC when query string parameters is incorrect
Let's imagine I have the following action
public ViewResult Products(string color)
{...}
and route which maps url "products" to this action.
According to SEO tips link /products?color=red
should return
200 OK
But link /products?someOtherParametr=someValue
404 Not found
So the question is - how to handle unexisting query parameters and return 404 in this case
Considering the accepted answer at What is the proper way to send an HTTP 404 response from an ASP.NET MVC action?, there is a special ActionResult
that could fulfill your expectation.
public class HomeController : Controller
{
public ViewResult Products(string color)
{
if (color != "something") // it can be replaced with any guarded clause(s)
return new HttpNotFoundResult("The color does not exist.");
...
}
}
Update:
public class HomeController : Controller
{
public ViewResult Products(string color)
{
if (Request.QueryString.Count != 1 ||
Request.QueryString.GetKey(0) != "color")
return new HttpNotFoundResult("the error message");
...
}
}
Validate this before executing the Action Method. This approach is valid for all Controller of you project or specific Action method.
Controller Action Methods
[attr] // Before executing any Action Method, Action Filter will execute to
//check for Valid Query Strings.
public class ActionResultTypesController : Controller
{
[HttpGet]
public ActionResult Index(int Param = 0)
{
return View();
}
[HttpPost]
public ActionResult Index(MyViewModel obj)
{
return View(obj);
}
}
Action Filter
public class attr : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.ActionParameters.Count == 0 &&
System.Web.HttpContext.Current.Request.QueryString.Count > 0)
{
//When no Action Parameter exists and Query String exists.
}
else
{
// Check the Query String Key name and compare it with the Action
// Parameter name
foreach (var item in System.Web.HttpContext
.Current
.Request.QueryString.Keys)
{
if (!filterContext.ActionParameters.Keys.Contains(item))
{
// When the Query String is not matching with the Action
// Parameter
}
}
}
base.OnActionExecuting(filterContext);
}
}
If you pay attention to the above code, we are checking the Action parameter as shown in the screen show below.
What can we do in case the QueryString passed does not exists in the Action Method Parameter? We can redirect the user to another page as shown in this link.
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary
{
{"action", "ActionName"},
{"controller", "ControllerName"},
{"area", "Area Name"},
{"Parameter Name","Parameter Value"}
});
Or
We can do like this. The below mentioned code will be written in the OnActionExecuting
Method Override
filterContext.Result = new HttpStatusCodeResult(404);
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
var actionParameters = filterContext.ActionParameters.Keys;
var queryParameters = filterContext
.RequestContext
.HttpContext
.Request
.QueryString
.Keys;
// if we pass to action any query string parameter which doesn't
// exists in action we should return 404 status code
if(queryParameters.Cast<object>().Any(queryParameter
=> !actionParameters.Contains(queryParameter)))
filterContext.Result = new HttpStatusCodeResult(404);
}
Actually, if you don't want to write this is in every controller, you should override DefaultControllerFactory