简体   繁体   English

ASP.NET MVC绑定与远程验证

[英]ASP.NET MVC Binding with Remote Validation

I have a model ModelA with a member toBeRemoteChecked and a model MapToA with a member valueToMap . 我有一个模型ModelA ,一个成员toBeRemoteChecked和一个模型MapToA与成员valueToMap Whenever I create an instance of ModelA , I also need an instance of MapToA , so I have a model CreateModelA which includes a member modelA and a member valueToMap . 每当我创建ModelA的实例时,我还需要一个MapToA实例,所以我有一个模型CreateModelA ,它包含一个成员modelA和一个成员valueToMap When the form is submitted, I add the modelA to the database table ModelA and create and add an instance to MapToA which consists of an id of modelA and the valueToMap . 提交表单时,我将modelA添加到数据库表ModelA并创建并向MapToA添加一个实例,该实例由modelAvalueToMap的id组成。 In Terms of code 在代码方面

public class ModelA
{
    [Key]
    public int ID { get; set; }
    [Required, Remote("isValid", "MyController", ErrorMessage = "not valid")]
    public string toBeRemoteChecked { get; set; }
}

public class MapToA
{
    [Key]
    public int Map_ID { get; set; }
    [Required]
    public int modelAID { get; set; }
    [Required]
    public int valueToMap { get; set; }
}

public class CreateModelA
{
    public ModelA modelA { get; set; };
    public int valueToMap { get; set; };
}

When I edit an instance of ModelA , values in MapToA don't matter (and in most cases there's more than one instance of mapToA with the same modelA id), but the remote validation of toBeRemoteChecked remains important. 当我编辑的一个实例ModelA ,价值观MapToA并不重要(在大多数情况下,根本的多个实例mapToA具有相同modelA ID),但远程验证toBeRemoteChecked仍然很重要。

My Problem: binding for the validation method: 我的问题:验证方法的绑定:

public ActionResult isValid(string toBeRemoteChecked) { ... }

If I leave it as it is, it is working when editing a ModelA , but not when I'm creating a ModelA via CreateModelA (I always get null value in toBeRemoteChecked ). 如果我保持原样,它在编辑ModelAModelA ,但在我通过CreateModelA创建ModelA没有(我总是在toBeRemoteChecked得到null值)。 When I use the BindPrefix 当我使用BindPrefix时

public ActionResult isValid([Bind(Prefix = "modelA.toBeRemoteChecked")] string toBeRemoteChecked) { ... }

it is working when I create a ModelA , but not when I'm editing it. 它在我创建ModelA时工作,但在我编辑它ModelA没有。

When I try to change the "name" in the Create.cshtml by adding a ... @Name = "toBeRemoteChecked" ... (instead of the modelA.toBeRemoteChecked that's created by the HTML helper) in the htmlAttributes of the @Html.TextBoxFor , then validation is working, but the binding of the value to the table get's lost and I get the error when the values are saved to the database (null value). 当我尝试通过增加在Create.cshtml改变“名” ... @Name = "toBeRemoteChecked" ... (而不是modelA.toBeRemoteChecked中的htmlAttributes那年代由HTML帮助创建) @Html.TextBoxFor ,然后验证工作正常,但是值与表的绑定会丢失,当值保存到数据库时我得到错误(空值)。

So, how do I achieve the different binding for creating and editing? 那么,如何实现创建和编辑的不同绑定?

So far, my workaround is to make ModelA and CreateModelA : IValidatableObject and check the member toBeRemoteChecked in my public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) method. 到目前为止,我的解决方法是创建ModelACreateModelA : IValidatableObject并在我的public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)方法中检查成员toBeRemoteChecked But that one displays the error messages on top of the form and not at the place of the TextFor box. 但是那个在表单顶部而不是在TextFor框的位置显示错误消息。

So: best solution: how to do the binding that the remote validation works in both cases? 那么:最佳解决方案:如何在两种情况下进行远程验证的绑定?

Second best: how to display the error messages of IValidatableObject near the object where it belongs to (and get the error messages right at hand, not after submitting) 第二好:如何在其所属的对象附近显示IValidatableObject的错误消息(并在提交时获取错误消息,而不是提交后)

Different ideas or solutions: welcome. 不同的想法或解决方案:欢迎。

Thanks. 谢谢。

An interesting issue, and similar to this question , which as an result I reported a issue at Codeplex, but it has not been resolved yet. 一个有趣的问题,与此问题类似,因此我在Codeplex报告了一个问题,但尚未解决。 The link includes a suggested modification to the jquery.validate.js file which would solve this (it strips the prefix) but that means you would need to maintain it whenever you update the script so not really desirable. 该链接包括对jquery.validate.js文件的建议修改,该文件将解决此问题(它会jquery.validate.js前缀),但这意味着您需要在更新脚本时进行维护,因此不太理想。

One option would be to change CreateModelA to inherit from ModelA and just add the int valueToMap property so that you never have a prefix - your always using @Html.TextBoxFor(m => m.toBeRemoteChecked) instead of @Html.TextBoxFor(m => m.modelA.toBeRemoteChecked) 一种选择是将CreateModelA更改为继承自ModelA ,只需添加int valueToMap属性,以便永远不会有前缀 - 总是使用@Html.TextBoxFor(m => m.toBeRemoteChecked)而不是@Html.TextBoxFor(m => m.modelA.toBeRemoteChecked)

Also, [Remote] is client side only validation, which means you still need to perform the validation in the server when you post. 此外, [Remote]仅限客户端验证,这意味着您仍需要在发布时在服务器中执行验证。 So you could just accept that you don't have client side validation for the property, and instead add a ModelState error in the POST methods(s) for the property and return the view so that its displayed in the associated ValidationMessageFor() element 所以你可以接受你没有对属性进行客户端验证,而是在属性的POST方法中添加ModelState错误并返回视图,以便它显示在关联的ValidationMessageFor()元素中

Side note: The fact your model has a [Key] attribute suggests this is a data model, not a view model, and [Remote] is a view specific attribute. 附注:您的模型具有[Key]属性的事实表明这是数据模型,而不是视图模型, [Remote]是视图特定属性。 You should be using view models, especially when editing data. 您应该使用视图模型,尤其是在编辑数据时。 (refer What is ViewModel in MVC? ) (参考MVC中的ViewModel什么?

I found a solution without inheritance (and without view models) that solves my binding problem with just little change to my code. 我找到了一个没有继承(并且没有视图模型)的解决方案,只需对代码进行少量更改即可解决我的绑定问题。

There's two ways of binding for remote validation, you can either just pass the member that has to be remote checked 有两种绑定远程验证的方法,你可以只传递必须远程检查的成员

public ActionResult isValid(string toBeRemoteChecked) { ... }

or you can pass the instance of the class of that member. 或者您可以传递该成员的类的实例。

public ActionResult isValid(ModelA modelA) { ... }

Inside the second variant, of course, you have to replace toBeRemoteChecked with modelA.toBeRemoteChecked . 里面的第二个变体,当然,你必须更换toBeRemoteCheckedmodelA.toBeRemoteChecked On this second version the binding works in both cases - when editing and also when creating my instance of ModelA in the context above. 在第二个版本中,绑定适用于两种情况 - 编辑时以及在上面的上下文中创建ModelA实例时。 In order to make the binding work, it's crucial that the parameter name of the remote validation method matches the member name in the CreateModelA , ie modelA in my case. 为了使绑定工作,远程验证方法的参数名称与CreateModelA中的成员名称匹配是至关重要的,即在我的情况下是modelA

In case you have a very complex model, you can just initialize the parameter modelA with the members you want to use by using bind/include, ie in my case I'd use 如果你有一个非常复杂的模型,你可以使用bind / include初始化参数modelA和你想要使用的成员,即在我的情况下我会使用

public ActionResult isValid([Bind(Include = "toBeRemoteChecked")] ModelA modelA) { ... }

By default (without Include), all other members will remain null or have a default value - so you need to use Include only if you need other members for validation as well - in my case, I would have the same when omitting the Include) 默认情况下(没有Include),所有其他成员将保持为null或具有默认值 - 因此,只有在需要其他成员进行验证时才需要使用Include - 在我的情况下,省略Include时也会如此

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM