简体   繁体   English

实现一个类级别的验证属性,该属性将写入类中的属性

[英]Implementing a class-level validation attribute that writes to a property inside the class

I'm building an ASP.NET MVC site where I want to decorate my ViewModels with validation attributes. 我正在建立一个ASP.NET MVC网站,我想在其中装饰带有验证属性的ViewModel。 One of the things I want to validate is that the address that a user submits through a form is geocodable. 我要验证的一件事是,用户通过表单提交的地址是可地理编码的。 For that, I have already created a custom ValidationAttribute and have applied to my StreetAddress property. 为此,我已经创建了一个自定义的ValidationAttribute并将其应用于我的StreetAddress属性。

This is all good, except that I am actually making two geocoding requests - one in my ViewModel for validation and another in my Controller to input the latitude and longitude into my database. 这一切都很好,除了我实际上在进行两个地理编码请求-一个在ViewModel中进行验证,另一个在我的Controller中将纬度和经度输入到数据库中。 I want to cut down on unnecessary network usage and delays, so I need to pass the result from the validation geocode into my controller. 我想减少不必要的网络使用和延迟,因此我需要将验证地理代码的结果传递到我的控制器中。

To accomplish such a thing, I think I should create a Latitude and Longitude property in my ViewModel. 为了完成这样的事情,我认为我应该在ViewModel中创建一个Latitude和Longitude属性。 The View itself won't touch these 2 properties, but the validation attribute will either report a failure in geocoding and return the View or write the results into the properties. View本身不会涉及这2个属性,但是validate属性将报告地理编码失败并返回View或将结果写入属性。

For a validation attribute to access 3 properties, it has to be applied to the whole class. 为了使验证属性访问3个属性,必须将其应用于整个类。 I don't know how to do that yet, but that's what this question is for. 我还不知道该怎么做,但这就是这个问题的目的。

UPDATE: Thanks to this answer , I have figured out how to create a class-level validation attribute. 更新:由于有了这个答案 ,我已经弄清楚了如何创建一个类级别的验证属性。 The link in the answer also demonstrates how to read the contents of a property inside the class (via Reflection). 答案中链接还演示了如何读取类内部属性的内容(通过反射)。 I still haven't figured out how to write to a property, though. 不过,我仍然没有弄清楚如何写属性。


My Questions 我的问题

How do I create a ValidationAttribute that can be applied to a whole class? 如何创建可应用于整个类的 ValidationAttribute Below, I have posted the code that I want to transfrom into an attribute that can be applied to my ViewModel: 在下面,我已经发布了要转换为可以应用于ViewModel的属性的代码:

 
 
 
 
  
  
  public class GeocodableAttribute : ValidationAttribute { public GeocodableAttribute() : base() { ErrorMessage = "We weren't able to find that location."; } public override bool IsValid(object value) { if (value == null) //we don't care if it's required or not. { return true; } var address = (string)value; var response = Geocoder.CallGeoWS(address.Trim()); if(response.Status=="ZERO_RESULTS") { return false; } return true; } }
 
 
  


How do I have the attribute write to certain properties in the class that it is applied to? 如何让属性写入应用该类的某些属性 When I apply this attribute to my ViewModel, I want it to write successful geocoding results into two properties and return true . 当我将此属性应用于ViewModel时,我希望它将成功的地理编码结果写入两个属性并return true How can I implement that? 我该如何实施?

UPDATE #2: I think I just figured out how to write to a property. 更新#2:我想我只是想出了如何写属性。 Should the following code work? 以下代码应该工作吗?

    private static void WritePropertyValue(object obj, string propertyName, object valueToWrite)
    {
        if (obj == null) return null;
        var type = obj.GetType();
        var propertyInfo = type.GetProperty(propertyName);
        if (propertyInfo == null) return null;
        propertyInfo.SetValue(obj, valueToWrite, null);
    }

Will this break client-side validation for other attributes/properties? 这会中断客户端对其他属性/属性的验证吗? I have other properties in my ViewModel that I have decorated with built-in ValidationAttributes, such as [Required] and [Range] . 我的ViewModel中还有其他用内置ValidationAttributes装饰的属性,例如[Required][Range] I have also enabled client-side validation for them. 我还为它们启用了客户端验证。 Will applying my new attribute to the whole ViewModel class completely break client-side validation or will validation for the other properties be performed on the client and then total validation will be performed on the server? 将我的新属性应用于整个ViewModel类会完全破坏客户端验证,还是会在客户端上执行其他属性的验证,然后在服务器上执行总验证?

1) You can't access the outer class via a property level ValidationAttribute. 1)您不能通过属性级别的ValidationAttribute访问外部类。

You could use a custom model binder to accomplish this. 您可以使用自定义模型活页夹来完成此操作。 Simply detect the attributes and validate accordingly. 只需检测属性并进行相应验证。

Creating a custom model binder: http://www.singingeels.com/Articles/Model_Binders_in_ASPNET_MVC.aspx 创建自定义模型活页夹: http : //www.singingeels.com/Articles/Model_Binders_in_ASPNET_MVC.aspx

2) No. Did you try? 2)不,您尝试过吗?

This is almost a duplicate. 这几乎是重复的。 I'd check out the question and answers for my dupe submission. 我会为我的骗局提交问题和答案。 It may contain a separate technique, class level validation, that may do what you need. 它可能包含一项单独的技术,即类级别验证,可以满足您的需要。

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

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