My entities: ( the PersonModel should have an address on type AddressOne or AddressTwo (and maybe others) so the PersonModel has an object type for the address field. )
我的实体:( PersonModel应该有一个AddressOne或AddressTwo类型的地址(可能还有其他),所以PersonModel有一个地址字段的对象类型。)
public class Person
{
public int PersonId { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public object Address { get; set; }
}
public class AddressOne
{
public string Street { get; set; }
public string City { get; set; }
}
public class AddressTwo
{
public string Province { get; set; }
public string State { get; set; }
}
the models: (I pass an hidden field in typeOfAddress to match the correct address after the form submit)
模型:(我在typeOfAddress中传递一个隐藏字段,以匹配表单提交后的正确地址)
public class PersonModel
{
private System.Type _typeOfAddress;
private object _address;
[Required]
public int PersonId { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Surname { get; set; }
public System.Type typeOfAddress
{
get { return _typeOfAddress; }
set { _typeOfAddress = value; }
}
public object Address
{
get {
return _address;
}
set {
_address = value;
_typeOfAddress = _address.GetType();
}
}
}
public class AddressOneModel
{
[Required]
public string Street { get; set; }
[Required]
public string City { get; set; }
}
public class AddressTwoModel
{
[Required]
public string Province { get; set; }
[Required]
public string State { get; set; }
}
My view (for address field I have ad Editor Template that is omitted in this code):
我的观点(对于地址栏我有广告编辑模板,在此代码中省略):
@using (Html.BeginForm()) {
<ul>
<li>
PersonId: @Html.EditorFor(model => model.PersonId)
</li>
<li>
Name: @Html.EditorFor(model => model.Name)
</li>
<li>
Surname: @Html.EditorFor(model => model.Surname)
</li>
<li>
Address:
</li>
<li>
@Html.HiddenFor(model => model.typeOfAddress)
@Html.EditorFor(model => model.Address)
</li>
</ul>
<button type="submit">Submit</button>
}
and then my controller: (in this example I load AddressOne in the model but should be One or Two depends at the run time...)
然后是我的控制器:(在这个例子中,我在模型中加载了AddressOne但应该是一个或两个取决于运行时......)
[HttpGet]
public ActionResult Index()
{
PersonModel myPerson = new PersonModel();
myPerson.PersonId = 1;
myPerson.Name = "Michael";
myPerson.Surname = "Douglas";
AddressOneModel Address = new AddressOneModel();
Address.Street = "5th Avenue";
Address.City = "New York";
myPerson.Address = Address;
return View(myPerson);
}
[HttpPost]
public ActionResult Index([ModelBinder(typeof(PersonModelBinder))]PersonModel myPerson)
{
if (ModelState.IsValid) {
// some things here
}
return View();
}
then there is the Model Binder for PersonModel:
然后是PersonModel的Model Binder:
public class PersonModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
PersonModel bindedModel = new PersonModel();
foreach (var Property in typeof(PersonModel).GetProperties())
{
PropertyInfo info = bindedModel.GetType().GetProperty(Property.Name);
object castedInfo = new object();
var uType = info.PropertyType;
if (uType == typeof(string))
{
castedInfo = bindingContext.ValueProvider.GetValue(Property.Name).AttemptedValue.ToString();
}
else if (uType == typeof(Type))
{
castedInfo = Type.GetType(bindingContext.ValueProvider.GetValue(Property.Name).AttemptedValue.ToString());
}
else if (uType == typeof(object))
{
string objType = bindingContext.ValueProvider.GetValue("typeOfAddress").AttemptedValue;
object address = (object)Activator.CreateInstance(Type.GetType(objType));
// another foreach as previous
}
else
{
object uCasted = (object)Activator.CreateInstance(info.PropertyType);
uCasted = Convert.ChangeType(bindingContext.ValueProvider.GetValue(Property.Name).AttemptedValue, Property.PropertyType);
castedInfo = uCasted;
}
info.SetValue(bindedModel, castedInfo, null);
}
return bindedModel;
}
Is this the correct way to implement the binding of PersonModel? And what about validation in [Post] controller?
这是实现PersonModel绑定的正确方法吗?那么[Post]控制器中的验证呢?
I seen also a way to use DefaultBinder in a way like this:
我也看到了一种以这种方式使用DefaultBinder的方法:
[ModelBinderType(typeof(PersonModel))]
public class PersonModelBinder : DefaultModelBinder
{
//...
}
but i don't find any reference of ModelBinderType in MVC3!! Any suggestion?
但我没有在MVC3中找到任何ModelBinderType的参考!有什么建议吗?
1 个解决方案
#1
2
It seems like you're trying to do this the hard way. You shouldn't need a model binder. What I would do is add each type of address to the model and on the page display the one that is not null. This would save you a lot of hassle.
看起来你正在努力做到这一点。你不应该需要一个模型绑定器。我要做的是将每种类型的地址添加到模型中,并在页面上显示非空的地址。这样可以省去很多麻烦。
public class PersonModel : IValidatableObject
{
private System.Type _typeOfAddress;
private object _address;
[Required]
public int PersonId { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Surname { get; set; }
public System.Type typeOfAddress
{
get { return (AddressOne ?? AddressTwo ?? AddressThree).GetType(); }
}
public AdressOneModel AddressOne {get;set;}
public AdressTwoModel AddressTwo {get;set;}
public AdressThreeModel AddressThree {get;set;}
}
Then maybe on the page do this
然后也许在页面上这样做
@using (Html.BeginForm())
{
<ul>
<li>
PersonId: @Html.EditorFor(model => model.PersonId)
</li>
<li>
Name: @Html.EditorFor(model => model.Name)
</li>
<li>
Surname: @Html.EditorFor(model => model.Surname)
</li>
<li>
Address:
</li>
<li>
@if(model.AddressOne != null)
{
Html.EditorFor(model => model.AddressOne)
}
else if(model.AddressTwo != null)
{
Html.EditorFor(model => model.AddressTwo)
}
</li>
</ul>
<button type="submit">Submit</button>
}
But it really depends on why you're doing this
但这实际上取决于你为什么要这样做
#1
2
It seems like you're trying to do this the hard way. You shouldn't need a model binder. What I would do is add each type of address to the model and on the page display the one that is not null. This would save you a lot of hassle.
看起来你正在努力做到这一点。你不应该需要一个模型绑定器。我要做的是将每种类型的地址添加到模型中,并在页面上显示非空的地址。这样可以省去很多麻烦。
public class PersonModel : IValidatableObject
{
private System.Type _typeOfAddress;
private object _address;
[Required]
public int PersonId { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Surname { get; set; }
public System.Type typeOfAddress
{
get { return (AddressOne ?? AddressTwo ?? AddressThree).GetType(); }
}
public AdressOneModel AddressOne {get;set;}
public AdressTwoModel AddressTwo {get;set;}
public AdressThreeModel AddressThree {get;set;}
}
Then maybe on the page do this
然后也许在页面上这样做
@using (Html.BeginForm())
{
<ul>
<li>
PersonId: @Html.EditorFor(model => model.PersonId)
</li>
<li>
Name: @Html.EditorFor(model => model.Name)
</li>
<li>
Surname: @Html.EditorFor(model => model.Surname)
</li>
<li>
Address:
</li>
<li>
@if(model.AddressOne != null)
{
Html.EditorFor(model => model.AddressOne)
}
else if(model.AddressTwo != null)
{
Html.EditorFor(model => model.AddressTwo)
}
</li>
</ul>
<button type="submit">Submit</button>
}
But it really depends on why you're doing this
但这实际上取决于你为什么要这样做