Asp.net mvc 如何在控制器操作上使用可选的通用参数?
我正在使用一个用于各种实体的BaseController。它们可能有Asp.net mvc 如何在控制器操作上使用可选的通用参数?,asp.net-mvc,generics,parameters,asp.net-mvc-controller,Asp.net Mvc,Generics,Parameters,Asp.net Mvc Controller,我正在使用一个用于各种实体的BaseController。它们可能有int或string主键,由表示 例如: [HttpGet] public ActionResult Create(TPk id) { return View(); } 在我尝试使用TPk作为可选参数之前,一切都很好 [HttpGet] public ActionResult Create(TPk id = default(TPk)) { return View(); } “可选”部分似乎不起作用 所以/co
int
或string
主键,由
表示
例如:
[HttpGet]
public ActionResult Create(TPk id)
{
return View();
}
在我尝试使用TPk
作为可选参数之前,一切都很好
[HttpGet]
public ActionResult Create(TPk id = default(TPk))
{
return View();
}
“可选”部分似乎不起作用
所以/controller/create/2
可以,但是/controller/create
给了我以下错误:
参数字典包含方法“System.Web.Mvc.ActionResult Create(Int32)”的非null类型“System.Int32”的参数“id”的null条目
该可选选项与int
或string
id配合使用效果良好。我可以调用/controller/create/2
和/controller/create
但是使用泛型类型参数TPk,无参数路由不再工作
我试过的 我已尝试将
TPk
参数设置为空,但无法编译:
类型“TPk”必须是不可为Null的值类型,才能将其用作泛型类型或方法“nullable”中的参数“T”
我已尝试根据-no-joy将参数名称从
id
更改为altId
我尝试过以完全相同的方式调用相同的方法,但使用了非泛型参数。例如:
public virtual async Task<ActionResult> Create(int id = default(int))
公共虚拟异步任务创建(int id=default(int))
这很有效
我尝试创建一个简单的新项目来隔离此代码。(如下所示)。这仍然会给无参数版本带来问题
简单代码测试 控制器
public abstract class BaseController<TPk> : Controller
{
public ActionResult Create(TPk id = default(TPk))
{
return View();
}
}
public class NewsController : BaseController<int>
{
}
公共抽象类BaseController:控制器
{
公共操作结果创建(TPk id=默认值(TPk))
{
返回视图();
}
}
公共类NewsController:BaseController
{
}
实体类
public class BaseDataModel<TPk>
{
public TPk Id { get; set; }
public string Title { get; set; }
}
public class PageDataModel : BaseDataModel<string>
{
public string Content { get; set; }
}
public class NewsDataModel : BaseDataModel<int>
{
public DateTime Date { get; set; }
}
公共类BaseDataModel
{
公共TPk Id{get;set;}
公共字符串标题{get;set;}
}
公共类PageDataModel:BaseDataModel
{
公共字符串内容{get;set;}
}
公共类NewsDataModel:BaseDataModel
{
公共日期时间日期{get;set;}
}
Asp.net约定主要基于反射。所以这可以解释这种行为。我还没有测试它是否真的不起作用,但我确信在这种状态下,您已经尝试创建一个新项目(POC)来排除任何自定义代码
也许可以通过深入研究路由(方法选择)和ModelBinder源代码来修复它
我只想创建一个不同的DuplicateRecord
操作
如果您不理解没有此注释的方法,这是一个很好的指示,您当前的代码可能有异味。(你在做同样的事情):
将共享内容提取到另一个方法(甚至可能是一个服务类),并为每个差异使用一个单独的方法
这就是说,通用CrudController的想法很可爱,几年前我自己也尝试过。但在尝试这样做的过程中,我引入了各种通用参数、策略模式、事件委托,以使所有可能性成为可能
- 如果需要加入,会发生什么
- 如果您需要交易,会发生什么
- 如何处理错误
- 如果crud逻辑需要1,2,3。。。决定要做什么的其他参数
- 软删除/硬删除
- 级联删除/限制删除
- 如果你
public async Task<IActionResult> CreateProduct(CancellationToken ct, ProductCreateModel model)
{
var result = await _productService.CreateAsync(model, ct);
//create response with some helpers... probably some ActionFilters
}
公共异步任务CreateProduct(CancellationToken ct,ProductCreateModel模型)
{
var result=await\u productService.CreateAsync(模型,ct);
//使用一些助手创建响应…可能是一些ActionFilter
}
泛型可以在一个简单的crud映射中进行压缩,其中每个视图都有一个实体,但它的伸缩性不是很好。所以,仔细想想你真正想要什么;) 谢谢!我可能会使用
DuplicateRecord
操作,但如果可能的话,我想了解为什么这不起作用。如果我找到答案,我会把它贴出来。。。我很感激通用积垢警告,我知道这是真的。这是我对该模式的第三次或第四次迭代,我刚刚解决了这些问题,创建了一个我可以使用的解决方案。“Asp.net约定在很大程度上基于反射。因此,这可能解释了这种行为。”你能在此基础上进行扩展吗?不确定,我应该扩展什么具体内容。这也许可以解释这种行为,我的意思是,反射可以引入人们意想不到的各种错误。例如,在这种情况下,泛型的处理似乎不正确。请看下面的示例。代码的一半是反射。
public async Task<IActionResult> CreateProduct(CancellationToken ct, ProductCreateModel model)
{
var result = await _productService.CreateAsync(model, ct);
//create response with some helpers... probably some ActionFilters
}