不知道为什么,但我的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 }
);
本地主机:8983 /测试/ SpecificEmpDetails / 1
Id将作为null,但是当我在调试期间将ID(在监视窗口中)从null更改为任何可用ID时,它会显示所需的员工数据。我完全搞砸了为什么id没有从url传递给控制器动作方法。
答案 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
属性,您可以看到默认注册的值提供程序(以及它们具有的优先顺序)。您还可以删除自定义值提供程序工厂并将其插入此属性。
因此,使用custom value provider,如果您真的想要,可以将一个名称映射到另一个名称。在这种情况下,您可以使密钥empId
的请求与路由值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");
}
如果您想要自定义路由,则必须约束路由,以使其与传递的每个值不匹配。在这种情况下,您只希望它匹配/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