Id 在 Action 方法中变为 Null
Id coming Null in the Action Method
不知道为什么,我的 Action 方法显示 id 为 null。我在 url 中传递了 id 但它仍然是 null
控制器动作方法
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; }
}
员工模型Class
[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
localhost:8983/Test/SpecificEmpDetails/1
Id 为 null,但是当我在调试期间将 ID(在手表 window 中)从 null 更改为任何可用 ID 时,它会显示所需的员工数据。我完全不明白为什么 id 没有从 url.
传递给控制器操作方法
Url 中的 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");
}
如果你不想改变你的方法,你必须使用这个 url 来修复它:
localhost:8983/Test/SpecificEmpDetails?empId=1
这里发生了两件不同的事情。
路由
首先,你的路由定义是:
routes.MapRoute(
name: "SpecificUser",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Test", action = "SpecificEmpDetails", id = UrlParameter.Optional }
);
您指定传递的路由值 的名称是{id}
。因此,任何匹配此路由的 URL 将被输入到 URL table 中,路由键 id
和在 URL 中传递的值。
例如,对于 URL /Test/SpecificEmpDetails/1
,您的路线 table 如下所示:
| Key | Value |
|-------------|---------------------|
| controller | Test |
| action | SpecificEmpDetails |
| id | 1 |
它看起来像这样的原因是因为您正在传递 URL 中的值,并且它们正在通过您定义的占位符转换为路由值。
价值提供者
MVC 获取操作方法参数值(或者从技术上讲,模型的任何值)的方式是通过值提供程序。
值提供者从多个位置查找键,例如查询字符串参数、表单值和路由值,以尝试将 键名称 与每个位置中的内容相匹配字典。如果action方法的参数名匹配,就会传值。如果没有匹配,该值将是数据类型的默认值。
您可以通过查看静态 ValueProviderFactories.Factories
属性 查看默认注册的值提供程序(以及它们的优先顺序)。您还可以删除 add/insert 自定义值提供程序工厂到此 属性.
因此,使用 custom value provider,如果您确实愿意,您 可以 将一个名称映射到另一个名称。在这种情况下,您可以使键 empId
的请求与路由值 id
.
匹配
也就是说,我建议您执行以下操作之一。
选项 1:使用默认路由,并坚持使用名称 "Id"
您提供的路由将无法在与默认路由相同的 MVC 应用程序中使用。原因是它将匹配 any URL 具有 0、1、2 或 3 个段 ,就像默认路由 一样。如果将此长度的 URL 传递给应用程序,它将匹配注册的第一个路由并忽略另一个。有关完整说明,请参阅 。
因此,如果您只在应用程序中使用一个路由,并使用 id
作为您的路由键和操作方法参数,一切都会相应地进行,并且 更简单 而不是使用自定义路由。
IMO,将 id
参数设为此特定 URL 的可选参数可能没有多大意义。无论如何,您的操作方法中没有代码来处理空 id
值。但是请注意,如果您传递 URL /Test/SpecificEmpDetails
,它仍然会匹配 Default
路由并匹配您的控制器操作(具有空值)。为避免这种情况,您可以插入一个 IgnoreRoute
来阻止 URL 在这种情况下进行匹配。
// 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");
}
方案二:使用自定义路由,参数名称改为"empId"
如果您想要自定义路由,您必须约束 路由,这样它就不会匹配传递的每个 值。在这种情况下,您只希望它匹配 /Test/SpecificEmpDetails/<SomeID>
,因此最简单的选择就是使用文字段而不是占位符。
您还需要,否则将是无法访问的执行路径。
如上所述,它仍然会匹配 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");
}
不知道为什么,我的 Action 方法显示 id 为 null。我在 url 中传递了 id 但它仍然是 null
控制器动作方法
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; }
}
员工模型Class
[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
localhost:8983/Test/SpecificEmpDetails/1
Id 为 null,但是当我在调试期间将 ID(在手表 window 中)从 null 更改为任何可用 ID 时,它会显示所需的员工数据。我完全不明白为什么 id 没有从 url.
传递给控制器操作方法Url 中的 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");
}
如果你不想改变你的方法,你必须使用这个 url 来修复它:
localhost:8983/Test/SpecificEmpDetails?empId=1
这里发生了两件不同的事情。
路由
首先,你的路由定义是:
routes.MapRoute(
name: "SpecificUser",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Test", action = "SpecificEmpDetails", id = UrlParameter.Optional }
);
您指定传递的路由值 的名称是{id}
。因此,任何匹配此路由的 URL 将被输入到 URL table 中,路由键 id
和在 URL 中传递的值。
例如,对于 URL /Test/SpecificEmpDetails/1
,您的路线 table 如下所示:
| Key | Value |
|-------------|---------------------|
| controller | Test |
| action | SpecificEmpDetails |
| id | 1 |
它看起来像这样的原因是因为您正在传递 URL 中的值,并且它们正在通过您定义的占位符转换为路由值。
价值提供者
MVC 获取操作方法参数值(或者从技术上讲,模型的任何值)的方式是通过值提供程序。
值提供者从多个位置查找键,例如查询字符串参数、表单值和路由值,以尝试将 键名称 与每个位置中的内容相匹配字典。如果action方法的参数名匹配,就会传值。如果没有匹配,该值将是数据类型的默认值。
您可以通过查看静态 ValueProviderFactories.Factories
属性 查看默认注册的值提供程序(以及它们的优先顺序)。您还可以删除 add/insert 自定义值提供程序工厂到此 属性.
因此,使用 custom value provider,如果您确实愿意,您 可以 将一个名称映射到另一个名称。在这种情况下,您可以使键 empId
的请求与路由值 id
.
也就是说,我建议您执行以下操作之一。
选项 1:使用默认路由,并坚持使用名称 "Id"
您提供的路由将无法在与默认路由相同的 MVC 应用程序中使用。原因是它将匹配 any URL 具有 0、1、2 或 3 个段 ,就像默认路由 一样。如果将此长度的 URL 传递给应用程序,它将匹配注册的第一个路由并忽略另一个。有关完整说明,请参阅
因此,如果您只在应用程序中使用一个路由,并使用 id
作为您的路由键和操作方法参数,一切都会相应地进行,并且 更简单 而不是使用自定义路由。
IMO,将 id
参数设为此特定 URL 的可选参数可能没有多大意义。无论如何,您的操作方法中没有代码来处理空 id
值。但是请注意,如果您传递 URL /Test/SpecificEmpDetails
,它仍然会匹配 Default
路由并匹配您的控制器操作(具有空值)。为避免这种情况,您可以插入一个 IgnoreRoute
来阻止 URL 在这种情况下进行匹配。
// 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");
}
方案二:使用自定义路由,参数名称改为"empId"
如果您想要自定义路由,您必须约束 路由,这样它就不会匹配传递的每个 值。在这种情况下,您只希望它匹配 /Test/SpecificEmpDetails/<SomeID>
,因此最简单的选择就是使用文字段而不是占位符。
您还需要
如上所述,它仍然会匹配 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");
}