Id在行动方法中出现空虚

时间:2016-07-10 16:25:08

标签: c# asp.net-mvc controllers

不知道为什么,但我的Action方法显示null为id。我在网址中传递了id,但仍然是空的

控制器操作方法

public ActionResult SpecificEmpDetails(string empId)
{
    CustomerBAL customer = new CustomerBAL();
    Customer custs = customer.Employees.Single(emp => emp.EmpID.ToString() == empId);
    ViewBag.Customers = custs;
    return View("EmpDetails");
}

视图

   <ul>
            <li>
                Customer ID : @ViewBag.Customers.EmpID
            </li>
            <li>
                Customer Name : @ViewBag.Customers.EmpName
            </li>
            <li>
                Customer Age : @ViewBag.Customers.EmpAge
            </li>
            <li>
                Customer Gender : @ViewBag.Customers.EmpGender
            </li>
            <li>
                Customer Salary : @ViewBag.Customers.EmpSalary
            </li>
        </ul>

员工数据库上下文

public class CustomerBAL : DbContext
{
    public DbSet<Customer> Employees { get; set; }
}

员工模型类

[Table("tblEmployee")]
public class Customer
{
    [Key]
    public int EmpID { get; set; }
    public string EmpName { get; set; }
    public string EmpGender { get; set; }
    public int EmpAge { get; set; }
    public int EmpSalary { get; set; }
}

路线配置

routes.MapRoute(
               name: "SpecificUser",
               url: "{controller}/{action}/{id}",
               defaults: new { controller = "Test", action = "SpecificEmpDetails", id = UrlParameter.Optional }
           );

URL

本地主机:8983 /测试/ SpecificEmpDetails / 1

Id将作为null,但是当我在调试期间将ID(在监视窗口中)从null更改为任何可用ID时,它会显示所需的员工数据。我完全搞砸了为什么id没有从url传递给控制器​​动作方法。

2 个答案:

答案 0 :(得分:2)

这里有两件不同的事情。

路由

首先,您的路线定义是:

routes.MapRoute(
           name: "SpecificUser",
           url: "{controller}/{action}/{id}",
           defaults: new { controller = "Test", action = "SpecificEmpDetails", id = UrlParameter.Optional }
       );

您指定传递的路由值的名称为{id}。因此,匹配此路由的任何URL都将输入到URL表中,路由密钥为id,并且该值将在URL中传递。

例如,使用网址/Test/SpecificEmpDetails/1,您的路由表如下所示:

| Key         | Value               |
|-------------|---------------------|
| controller  | Test                |
| action      | SpecificEmpDetails  |
| id          | 1                   |

它看起来是这样的原因是因为您传递了URL中的值,并且它们通过您定义的占位符转换为路由值。

价值提供者

MVC获取操作方法参数值(或技术上,模型的任何值)的方式是通过值提供程序

值提供程序从多个位置查找键,例如查询字符串参数,表单值和路由值,以尝试将键名与每个词典中的内容进行匹配。如果action方法的参数名称匹配,则会传递值。如果没有匹配项,则该值将是数据类型的默认值。

通过查看静态ValueProviderFactories.Factories属性,您可以看到默认注册的值提供程序(以及它们具有的优先顺序)。您还可以删除自定义值提供程序工厂并将其插入此属性。

enter image description here

因此,使用custom value provider,如果您真的想要,可以将一个名称映射到另一个名称。在这种情况下,您可以使密钥empId的请求与路由值id匹配。

那就是说,我建议你做以下其中一项。

选项1:使用默认路由,并坚持使用名称“Id”

您提供的路由在默认路由的同一MVC应用程序中不起作用。原因是它将匹配具有0,1,2或3个段的任何 URL,就像默认路由一样。如果将此长度的URL传递给应用程序,它将匹配注册的第一个路由,并忽略另一个路由。有关完整说明,请参阅Why map special routes first before common routes in asp.net mvc?

因此,如果您只在应用程序中使用一个路由,并使用id作为路由键和操作方法参数,则所有内容都将相应地流动,并且更简单比使用自定义路线。

IMO,为这个特定的URL设置id参数可能没有多大意义。您的操作方法中没有代码来处理空id值。但请注意,如果您传递了网址/Test/SpecificEmpDetails,它仍会匹配Default路由,并且无论如何都会匹配您的控制器操作(使用空值)。为避免这种情况,您可以在此情况下插入IgnoreRoute来阻止匹配网址。

// Ignore the URL if it is passed with no id, so you get a 404 not found
routes.IgnoreRoute("Test/SpecificEmpDetails");

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

你的行动方法:

public ActionResult SpecificEmpDetails(string id)
{
    CustomerBAL customer = new CustomerBAL();
    Customer custs = customer.Employees.Single(emp => emp.EmpID.ToString() == id);
    ViewBag.Customers = custs;
    return View("EmpDetails");
}

选项2:使用自定义路由并将参数名称更改为“empId”

如果您想要自定义路由,则必须约束路由,以使其与传递的每个值不匹配。在这种情况下,您只希望它匹配/Test/SpecificEmpDetails/<SomeID>,因此最简单的选择就是使用文字段而不是占位符。

您还需要place your custom route first before the default route,否则它将是无法访问的执行路径。

如上所述,它仍然会与Default路由匹配,并且无论如何都会匹配您的控制器操作(null值,因为id不等于empId)。因此,在这种情况下,您还应该插入IgnoreRoute来阻止URL匹配。

// Ignore the URL if it is passed with no empId, so you get a 404 not found
routes.IgnoreRoute("Test/SpecificEmpDetails");

routes.MapRoute(
    name: "SpecificUser",
    url: "Test/SpecificEmpDetails/{empId}",
    defaults: new { controller = "Test", action = "SpecificEmpDetails" }
);

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

然后你可以在你的问题中使用你的方法。

public ActionResult SpecificEmpDetails(string empId)
{
    CustomerBAL customer = new CustomerBAL();
    Customer custs = customer.Employees.Single(emp => emp.EmpID.ToString() == empId);
    ViewBag.Customers = custs;
    return View("EmpDetails");
}

答案 1 :(得分:1)

网址中的Id不会传入empId,因为在MapRoute中,操作后的数字将转到Id而不是empId

像这样改变你的行动,一切都会正常。

public ActionResult SpecificEmpDetails(string Id)
{
    CustomerBAL customer = new CustomerBAL();
    Customer custs = customer.Employees.Single(emp => emp.EmpID.ToString() == Id);
    ViewBag.Customers = custs;
    return View("EmpDetails");
}

如果您不想更改方法,则必须使用此网址进行修复:

localhost:8983/Test/SpecificEmpDetails?empId=1