Compound View Model object causing remote validation failure
I have used a pattern of compound view models for a few of the forms in this project. It works very well.
In this case I have a VendorAddress view model. I use Address(es) in a few places in this project so I made and Address view model object that I can re-use. Then I desided I want to do a very thorough checking of the state codes and zips so, I desided I would try to use remote validation and check the state and zip code aganst a stored set of tables in the database.
The problem is I am not getting values back to the remote action methods for the fields I'm asking for (in this case 开发者_StackOverflow中文版State and PostalCode). I believe this is because of the name mangleing that the MVC framework does for compound or sub types for id(s) for the inputs in this case it is making names like 'Address_Line1' and 'Address_State' and 'Address_PostalCode'.
Ultimately the question I have is, is there a way of turning off the pre-pended 'Address_' from the base view model object in a way that MVC framework can put it bak into the object after ther post of the form?
public class AddressViewModel
{
[ScaffoldColumn(false)]
public int AddressId { get; set; }
[Required(ErrorMessage = "Please enter the first address line")]
public string Line1 { get; set; }
public string Line2 { get; set; }
public string Line3 { get; set; }
[Required(ErrorMessage = "Please enter a city name")]
public string City { get; set; }
[Required(ErrorMessage = "Please enter a state 2 letter code")]
[StringLength(2)]
[Remote("CheckState", "Validation", AdditionalFields = "PostalCode")]
public string State { get; set; }
[Required(ErrorMessage = "Please enter a postal code")]
[Remote("CheckZip", "Validation", AdditionalFields = "State")]
[Display(Name = "Zip / Postal Code")]
public string PostalCode { get; set; }
public string Country { get; set; }
}
public class VendorContactViewModel
{
public int VedorContactId { get; set; }
public int ContactVendorId { get; set; }
public int ContactId { get; set; }
[Required]
[Display(Name = "Contact Type")]
public byte ContactTypeId { get; set; }
public string ContactType { get; set; }
[Required]
[Display(Name = "Contact Info")]
public string ContactInfo { get; set; }
[Display(Name = "Contact Label")]
public string ContactLabel { get; set; }
public IEnumerable<SelectListItem> ContactTypes { get; set; }
}
then in the form after rendering it looks like this:
<input type="text" value="" size="2" name="Address.State" maxlength="2" id="Address_State"
data-val-required="Please enter a state 2 letter code" data-val-remote-url="/Validation/CheckState"
data-val-remote-additionalfields="*.State,*.PostalCode" data-val-remote="&#39;State&#39; is invalid."
data-val-length-max="2" data-val-length="The field State must be a string with a maximum length of 2."
data-val="true" class="input-validation-error">
I get the remote call but there is nothing in the parameters "State" and "PostalCode", so the unobtrusive routines are firing but I think it does not know where to look for the data even though I have type something in the mensioned fields. As you can see in the rendered code the id="Address_State" and the data-val-remote-additionalfields=".State,.PostalCode"
Thanks for your time and effort,
Irv
Try specifying a prefix to help the model binder correctly bind the Address.PostalCode
and Address.State
request values to their corresponding action parameters:
public ActionResult CheckState(
[Bind(Prefix = "Address.State")]string State,
[Bind(Prefix = "Address.PostalCode")]string PostalCode
)
{
...
}
I ran into this issue, but needed to use the same ViewModel in multiple views with different prefixes. I ended up writing javascript that modified the jQuery remote validation rules so they did not include any prefix:
$('[data-val-remote]').each(function () {
// overwrite the remote rule data so that it sends non-prefixed property name to the server
var remoteRule = $(this).rules().remote;
var newData = {};
var keys = Object.keys(remoteRule.data);
for (var i = 0; i < keys.length; i++) {
var nonPrefixedPropertyName = $(keys[i].split('.')).last()[0];
newData[nonPrefixedPropertyName] = remoteRule.data[keys[i]];
}
remoteRule.data = newData;
});
精彩评论