简体   繁体   中英

C# MVC ActionResult

I am learning ASP.MVC and stuck on a issue and dont know whether this is the way to solve the issue.

I have a controller with the following actionresult:

[Route("customers/show/{id}")]
public ActionResult Show(int id)
{
    var customer = GetCustomers().SingleOrDefault(c => c.Id == id);
    return View(customer);
}

The issue is as long as the integer is being sent as parameter then no problem. For example "/customers/show/123", but If someone try to access like this "/customers/show/12xyz" then it will throw an ugly error like this:

Server Error in '/' Application.
The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult Show(Int32)' in 'MyApp.Controllers.CustomersController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Parameter name: parameters

I want to avoid that application error so I tried solving like this. Is this the correct MVC way or is there any other smarter way?

[Route("customers/show/{id}")]
public ActionResult Show(string id)
{
    int custId = 0;
    int.TryParse(id, out custId);

    var customer = GetCustomers().SingleOrDefault(c => c.Id == custId);
    return View(customer);
}
[Route("customers/show/{id}")]
public ActionResult Show(int? id)
{
    var customer = GetCustomers().SingleOrDefault(c => c.Id == id);
    if (customer == null)
    {
        return HttpNotFound();
    }
    return View(customer);
}

This way, if there is nothing in the database/file/wherever you're searching for that ID, you return a result to the customer that lets them know this; in this case, an HTTP Error 404: Not Found.

It really depends on how you want to handle those problems. If someone is going directly to a detail page by bypassing your searching UI, then you can either return a 404 not found page or you could redirect them directly to the search page, depending on your use case.

The reason why you are getting this particular error is that you don't have a type constraint on the route it self. You really only want to deal with an int. However, if you put that constraint on there and the value isn't an int, then the generic 404 error handling is going to kick in. It all depends on what your business requirements are here, so I'll show you a few options:

Handle all details and redirect to search when not found:

[Route("customers/show/{id}")]
public ActionResult Show(string id)
{
    if (!int.TryParse(id, out var parsedId)) {
        return Redirect("/customers");  // Or return HttpNotFound();
    }

    // Note: You should really pass your Id into GetCustomers somehow or else it'll pull 
    //everything from your database first and then find the one customer in memory
    var customer = GetCustomers().FirstOrDefault(c => c.Id == parsedId);

    if (customer == null)
    {
        return Redirect("/customers");  // Or return HttpNotFound();
    }
    return View(customer);
}

Any non-int will be handled by the generic 404:

[Route("customers/show/{id:int}")]
public ActionResult Show(int? id)
{
    if (!id.HasValue) {
            return Redirect("/customers");  // Or return HttpNotFound();
    }

    var customer = GetCustomers().FirstOrDefault(c => c.Id == id.Value);
    if (customer == null)
    {
        return Redirect("/customers");  // Or return HttpNotFound();
    }
    return View(customer);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM