我已经和MVC一起开发了几年了,有人认为我最初的教学是HttpPost
行动,第一的事情总是< / strong> do是对ModelState.IsValid执行检查,所以......
[HttpPost]
public ActionResult Edit(ViewModel form) {
if(ModelState.IsValid) {
// Do post-processing here
}
}
我现在遇到一个问题,我在表单中传递了哈希ID。如果它为0,则为新记录,如果其高于0则表示我正在编辑。如果我的ModelState.IsValid返回false,我需要再次设置一些下拉列表数据,然后返回到具有相同模型的Edit视图。要设置失败后返回到表单的其中一些项目,我需要知道未散列的数字,但在ModelState.IsValid中取消它会使它在else语句中不可用。
因此,执行以下操作是否可以接受: -
[HttpPost]
public ActionResult Edit(ViewModel form) {
int myID = 0;
if(/** unhashing is successful...**/)
{
if(ModelState.IsValid) {
// Do post-processing here
}
else
{
// Setup dropdowns using unhashed ID and return original view...
}
}
}
请注意,ModelState.IsValid不是HttpPost中的第一个测试。那可以接受吗?如果没有,是否有更合适的方式来做这样的逻辑?
谢谢!
答案 0 :(得分:1)
在您的来源中,您似乎已经写了一些关于 unhashing 的评论,但这样的术语并不存在。散列函数的目的是不可逆转的。我认为另一方面,你的意思是解密查询字符串值。理想情况下,此解密应在视图模型的自定义模型绑定器中进行,并将此参数的ModelState.IsValid
值设置为false。因此,在控制器操作中,您需要检查的是此布尔参数。控制器操作不应解密任何查询字符串或任何参数。这应该在MVC执行管道中更早地完成。自定义模型绑定器甚至自定义授权过滤器更适合此方案。
让我们举个例子:
public class ViewModel
{
public int Id { get; set; }
... some other stuff around
}
现在您可以为此视图模型编写自定义模型绑定器:
public class MyDecryptingBinder : DefaultModelBinder
{
protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor)
{
if (propertyDescriptor.Name == "Id")
{
var idParam = bindingContext.ValueProvider.GetValue("Id");
if (idParam != null)
{
string rawValue = idParam.RawValue as string;
int value;
if (this.DecryptId(rawValue, out value))
{
propertyDescriptor.SetValue(bindingContext.Model, value);
return;
}
}
}
base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
}
private bool DecryptId(string raw, out int id)
{
// TODO: you know what to do here: decrypt the raw value and
// set it to the id parameter, or just return false if decryption fails
}
}
现在,您可以在引导时(Application_Start
)向视图模型注册此自定义模型绑定器:
ModelBinders.Binders.Add(typeof(ViewModel), new MyDecryptingBinder());
然后您的控制器操作将如下所示:
[HttpPost]
public ActionResult Index(ViewModel model)
{
if (ModelState.IsValid)
{
// The decryption of the id parameter has succeeded, you can use model.Id here
}
else
{
// Decryption failed or the id parameter was not provided: act accordingly
}
}