asp.net-mvc - 如何在控制器操作上使用可选的通用参数?
问题描述
我正在使用用于各种实体的 BaseController。它们可能具有主键int
或string
主键,由 . 表示<TPk>
。
例如:
[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)”的不可空类型“System.Int32”的参数“id”的空条目
可选的适用于int
或string
id。我可以打电话/controller/create/2
AND /controller/create
。
但是使用泛型类型参数TPk
,无参数路由不再有效。
我试过的
我试过使TPk
参数可以为空,但它不会编译:
类型“TPk”必须是不可为空的值类型,才能将其用作泛型类型或方法“Nullable”中的参数“T”
我已经尝试根据这个问题id
将参数名称从更改为- 不高兴altId
我尝试以完全相同的方式调用相同的方法,但使用非泛型参数。例如:
public virtual async Task<ActionResult> Create(int id = default(int))
这工作得很好。
我尝试创建一个简单的新项目来隔离此代码。(如下所示)。这仍然给无参数版本带来问题。
简单代码测试
控制器
public abstract class BaseController<TPk> : Controller
{
public ActionResult Create(TPk id = default(TPk))
{
return View();
}
}
public class NewsController : BaseController<int>
{
}
实体类
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; }
}
解决方案
Asp.net 约定很大程度上基于反射。所以这可以解释这种行为。我还没有测试它是否真的不起作用,但我确信在这种状态下您已经尝试创建一个新项目 (POC) 以排除任何自定义代码。
也许可以通过更深入地研究路由(方法选择)和 ModelBinder 源代码来修复它......
我只会创建一个不同的DuplicateRecord
动作。
如果您在没有此注释的情况下不理解您的方法,则说明您当前的代码可能有异味。(你在做同样的事情):
// duplicates existing record if id is passed in, otherwise from scratch
将共享的东西提取到另一个方法(甚至可能是一个服务类),并为每个差异提供一个单独的方法。
也就是说,通用 CrudController 的想法很可爱,几年前我自己尝试过。但在尝试这样做时,我引入了各种通用参数、策略模式、事件委托,以使所有可能性成为可能。
- 如果您需要加入,会发生什么?
- 如果您需要交易会发生什么?
- 你如何处理错误?
- 如果您的 crud 逻辑需要 1、2、3 ... 附加参数来决定要做什么,会发生什么?
- 软删除/硬删除?
- 级联删除/限制删除?
- 如果你...
我写了这么多代码,很高兴能恢复到好的旧的非泛型代码。如果在服务中抽象出来,ActionMethods 真的不需要变大。
public async Task<IActionResult> CreateProduct(CancellationToken ct, ProductCreateModel model)
{
var result = await _productService.CreateAsync(model, ct);
//create response with some helpers... probably some ActionFilters
}
泛型可以在一个简单的 crud 映射中正常工作,其中每个视图都有一个确切的实体,但它不能很好地扩展。所以要小心并三思而后行你真正想要什么;)
推荐阅读
- java - 没有Deflater类的Java中的Deflate算法
- java - 从 Firebase 数据库中检索跨对象子对象
- javascript - window.open() 在 Safari ios 上不起作用
- java - 为什么变量 j 初始化不能在 for 循环的终止表达式中?
- powershell - 自动跟踪 RDP 会话
- python-3.x - 有一个 anaconda navigator 的实例已经在运行错误
- c# - 在 .net 命令行编译器中,当“out”选项中给出随机文件扩展名时会发生什么?
- python - 将来自多个站点的数据写入 JSON 文件 BeautifulSoup
- c# - Unity 中的 SQLite 数据库文件损坏
- javascript - 使用 AWS Lambda 自动创建静态站点客户端页面