ASP.NET MVC GetFullHtmlFieldId not returing valid

2019-05-25 04:53发布

I have taken a look at but it did not help me out

  1. GetFullHtmlFieldId returning incorrect id attribute value
  2. ASP.NET GetFullHtmlFieldId not returning valid id

Problem

Basically I have the following problem:

I have a custom validation attribute which requires to get the fieldId of the control

public class MyValidationAttribute : ValidationAttribute, IClientValidatable
{
    //...... Collapsed code
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        ViewContext vwContext = context as ViewContext;
        var fieldId = vwContext.ViewData.TemplateInfo.GetFullHtmlFieldId(metadata.PropertyName);

        //...... Collapsed code
        yield return clientValidationRule;
    }
    //...... Collapsed code
}

The result of GetFullHtmlFieldId depends on how I build my asp.net mvc page:

// Edit.cshtml or Create.cshtml    
@Html.EditorFor(model => model.MyBoolProperty)
// Shared/EditorTemplates/Boolean.cshtml
@Html.CheckBoxFor(model => model)

result of GetFullHtmlFieldId incorrect: MyBoolProperty_MyBoolProperty

// Edit.cshtml or Create.cshtml    
@Html.CheckBoxFor(model => model.MyBoolProperty)

result of GetFullHtmlFieldId correct: MyBoolProperty


Even with more complex editors I see this incorrect behavior

// Edit.cshtml or Create.cshtml  
@Html.EditorFor(model => model.JustAnArray[1].ComplexProperty.MyBooleanProperty)
// Shared/EditorTemplates/Boolean.cshtml
@Html.CheckBoxFor(model => model)

result of GetFullHtmlFieldId incorrect: JustAnArray_1__ComplexProperty_MyBoolProperty_MyBoolProperty

// Edit.cshtml or Create.cshtml  
@Html.CheckBoxFor(model => model.JustAnArray[1].ComplexProperty.MyBooleanProperty)

result of GetFullHtmlFieldId correct: JustAnArray_1__ComplexProperty_MyBoolProperty

Also this is returning correct value

// Edit.cshtml or Create.cshtml  
@Html.EditorFor(model => model.JustAnArray[1])
// Shared/EditorTemplates/ComplexProperty.cshtml
@Html.CheckBoxFor(model => model.MyBooleanProperty)

result of GetFullHtmlFieldId correct: JustAnArray_1__ComplexProperty_MyBoolProperty

It looks like that using @Html.CheckBoxFor(model => model), it gives incorrect results but when using @Html.CheckBoxFor(model => model.MyBoolProperty) it is working as expected

I have the same issue with other controls (like TextBoxFor)

Question

How can I get the proper fieldId of my control in my validation attribute, independent of how you build the page.

I'd rather use already existing methods (maybe the same methods as which are used by TextBoxFor and CheckBoxFor and other controls) than mimic this already existing functionality. If I mimic the generation of the fieldId, I have a change I don't take care of all situations where the ASP.NET controls take care of.

1条回答
疯言疯语
2楼-- · 2019-05-25 05:59

It seems that the valid prefix depends on the expressions used to build the page, and that isn't available to the GetClientValidationRules method. It would be great if someone has a solution for it, but as the method GetClientValidationRules is trying to initialize the data needed for the Javascript validation, you could try to resolve this on the client side.

On some of the default validation attributes like the [Compare], which depends on a second field, they set a parameter *.propertyName and in the unobtrusive adapter they replace the *. part with the valid prefix retrieved from the input name attribute. You could try a similar approach for the id.

However this would be needed if you were interested in another field. In this case it seems you are interested in the id of the very same input field that you are validating. You could then retrieve it from the input element itself. It will be available in both the unobtrusive adapter or the method itself:

//You could get it in the adapter and pass it to the validator in the "param"
adapters.add("dummy", function (options) {
    var fullFieldId = options.element.id;
    if (console) console.log("Full field id: " + fullFieldId);
    setValidationValues(options, "dummy", fullFieldId);
});
$jQval.addMethod("dummy", function (value, element, param) {
    var fullFieldId = param;
    //do whatever validation logic
    return true;
});

//You could also retrieve it directly in the validator method
$jQval.addMethod("dummy", function (value, element, param) {
    var fullFieldId = element.id;
    //do whatever validation logic
    return true;
});
adapters.add("dummy", function (options) {
    setValidationValues(options, "dummy", {});
});

Hope it helps!

查看更多
登录 后发表回答