0

カスタムバインダーを使用してコンストラクターを処理し(必要)、デフォルトのモデルバインダーに残りのプロパティを通常どおり入力させたいと思います。

編集:もちろん、カスタムのものは最初に実行されます。

4

3 に答える 3

1

ありがとう、解決策を見つけたと思います。それは、defaultmodelbinder の createmodel メソッドをオーバーライドすることです。ここから追加のヘルプがありました: http://noahblu.wordpress.com/2009/06/15/modelbinder-for-objects-without-default-constructors/

mvcで行われた変更により、そのリンクに示されているようにモデルタイプを設定する代わりに、モデルメタデータを使用するように更新する必要がありました。これは、うまくいくと思われる最初の試みとして私が最終的に得たものです:

namespace NorthwindMVCApp.CustomBinders{

   public class NewShipperBinder<T> : DefaultModelBinder
{

    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        Type type1 = typeof(T);
        ConstructorInfo[] constructors = type1.GetConstructors();
        ConstructorInfo largestConstructor = constructors.OrderByDescending(x => x.GetParameters().Count()).First();
        ParameterInfo[] parameters = largestConstructor.GetParameters();
        List<object> paramValues = new List<object>();
        IModelBinder binder;
        string oldModelName = bindingContext.ModelName;
        foreach (ParameterInfo param in parameters)
        {
            string name = CreateSubPropertyName(oldModelName, param.Name);
            //bindingContext.ModelType = param.ParameterType;
            bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, param.ParameterType);
            bindingContext.ModelName = name;
            if (!System.Web.Mvc.ModelBinders.Binders.TryGetValue(param.ParameterType, out binder))
                binder = System.Web.Mvc.ModelBinders.Binders.DefaultBinder;
            object model = binder.BindModel(controllerContext, bindingContext);
            paramValues.Add(model);
        }
       // bindingContext.ModelType = typeof(T);
        bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, typeof(T));
        bindingContext.ModelName = oldModelName;
        Debug.WriteLine(Environment.StackTrace); 
        object obj = Activator.CreateInstance(type1, paramValues.ToArray());
        return obj;
    }
}

}

バインドされるクラスは次のとおりです。このすべての理由は、デフォルトのコンストラクターがないためです (null 不可がないことを確認するため)。

namespace Core.Entities{

[EntityAttribute()]
public class Shipper 
{

    protected Shipper() : this("Undefined")
    {

    }

    public Shipper(string CompanyName)
    {
        this.CompanyName = CompanyName;
        Orders = new List<Order>();
    }

    public virtual int ShipperID { get; set; }
    public virtual IList<Order> Orders { get; set; }
    public virtual string CompanyName { get; set; }
    public virtual string Phone { get; set; }

    public override bool Equals(object obj)
    {
        Shipper obj_Shipper;
        obj_Shipper = obj as Shipper;
        if (obj_Shipper == null)
        {
            return false;
        }
        if (obj_Shipper.CompanyName != this.CompanyName)
        {
            return false;
        }
        return true;
    }

    public override int GetHashCode()
    {
        return CompanyName.GetHashCode();
    }
}
}

ちなみにバインダーはglobal.asaxに以下のように含まれています。

            ModelBinders.Binders.Add(typeof(Shipper), new CustomBinders.NewShipperBinder<Shipper>());

したがって、エンティティの種類のリストを保持しているため、エンティティ クラス全体を (ループして) 追加するのは簡単です。

したがって、そのエンティティをデータベースに更新できました。

編集:ちょっとしたアイシング、ここにスタックトレースがあります:

at NorthwindMVCApp.CustomBinders.NewShipperBinder`1.CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) in C:\Users\####\Documents\Visual Studio 2010\Projects\TestFluentNHibernate\NorthwindMVC\NorthwindMVCApp\CustomBinders\NewShipperBinder.cs:line 37
   at System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
   at System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
   at System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor)
于 2011-09-25T23:33:13.273 に答える
1

Mo.の答えは正しいです。DefaultModelBinder から継承し、CreateModel をオーバーライドします。サンプルコードを提供するために投稿しています。

バインダー:

public class RegistrationViewModelBinder : DefaultModelBinder 
{
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        return new RegistrationViewModel(Guid.NewGuid());
    }
}

モデル:

public class RegistrationViewModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }    
    public Guid Id { get; private set; }

    public RegistrationViewModel(Guid id)
    {
        Id = id;
    }
}

プロパティが設定可能になる場合 (この場合は ID)、バインドから除外する必要があります。

[Bind(Exclude = "Id")]
public class RegistrationViewModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }

    public Guid Id { get; set; }
}
于 2011-09-25T09:00:36.207 に答える
0

DefaultModelBinderから既に継承していますか?意図したことを実行することはできないと思います。顧客モデルバインダーを作成し、それがIModelBinderを実装している場合、クラスは必要なすべてのアクションを実行する必要があります。

于 2011-09-23T22:21:40.007 に答える