3

抽象クラスのバインダーを作成しようとしています。バインダーは、使用するクラスの実装を決定します。

public abstract class Pet
{
    public string name { get; set; }
    public string species { get; set; }
    abstract public string talk { get; }
}

public class Dog : Pet
{
    override public string talk { get { return "Bark!"; } }
}
public class Cat : Pet
{
    override public string talk { get { return "Miaow."; } }
}
public class Livestock : Pet
{
    override public string talk { get { return "Mooo. Mooo. Fear me."; } }
}

だから私はペットを連れて行くコントローラーを持っています、バインダーはそれが犬、猫、家畜のどれであるかを(種のひもに応じて)決定します。

public class PetBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var values = (ValueProviderCollection)bindingContext.ValueProvider;
        var name = (string)values.GetValue("name").ConvertTo(typeof(string));
        var species = (string)values.GetValue("species").ConvertTo(typeof(string));
        if (species == "dog")
        {
            return new Dog { name = name, species = "dog" };
        }
        else if (species == "cat")
        {
            return new Cat { name = name, species = "cat" };
        }
        else
        {
            return new Livestock { name = name, species = species };
        }
    }
}


public class HomeController : Controller
{
    public JsonResult WorksFine(Pet pet)
    {
        return Json(pet);
    }

    public JsonResult DoesntWork(List<Pet> pets)
    {
        return Json(pets);
    }
}

これはうまく機能しますが、ペットが別の構造(List<Pet>または別のオブジェクトなど)に入るとすぐに、NullReferenceException(var name = (string)values.GetValue("name").ConvertTo(typeof(string)); PetBinderの行)が発生します。私は何が間違っているのですか?

テストするPersonクラスを追加しました。また、NullReferenceExceptionが発生しました。

public class Person
{
    public string name { get; set; }
    public Pet pet { get; set; }
}
public class HomeController : Controller
{
    public JsonResult PersonAction(Person p)
    {
        return Json(p);
    }
}

ccurrensは、var name = (string)values.GetValue("name").ConvertTo(typeof(string)); nullが返された理由は、リストから値を取得できなかったためだと述べました。

名前が付けられているのはわかりますが、オブジェクト内の場合は名前が付けられ[n].name[n].species単一の場合は名前が付けられているだけです。List<Pet>Personpet.namepet.speciesPetnamespecies

解決

[n]の正しいプレフィックス(またはpetその他)を持つパラメーター名を取得するためにGetValue、次のコードを使用しました。

bool hasPrefix = bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName);
string prefix = ((hasPrefix)&&(bindingContext.ModelName!="")) ? bindingContext.ModelName + "." : "";

誰かが興味を持っているなら、私はこの答えDefaultModelBinderに似たものを使うことから継承することになりました。これが私が使用した完全なコードです:

public class DefaultPetBinder : DefaultModelBinder
{
    protected override object CreateModel(ControllerContext controllerContext,ModelBindingContext bindingContext,Type modelType)
    {
        //https://stackoverflow.com/questions/5460081/asp-net-mvc-3-defaultmodelbinder-inheritance-problem

        bool hasPrefix = bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName);
        string prefix = ((hasPrefix)&&(bindingContext.ModelName!="")) ? bindingContext.ModelName + "." : "";

        // get the parameter species
        ValueProviderResult result;
        result = bindingContext.ValueProvider.GetValue(prefix+"species");


        if (result.AttemptedValue.Equals("cat"))
            return base.CreateModel(controllerContext,bindingContext,typeof(Cat));
        else if (result.AttemptedValue.Equals("dog"))
            return base.CreateModel(controllerContext,bindingContext,typeof(Dog));
        return base.CreateModel(controllerContext, bindingContext, typeof(Livestock)); // livestock
    }  

}
4

1 に答える 1

0

エラーが発生している行では、valuesnullであるか、GetValue("name")返されるものがnullである可能性があります。

メソッドを呼び出すときにList<Pet>、ValueProviderはList個々の値ではなく全体を返すと想定しているため、値はクラスに存在しPetないため、値を取得できません。"name"List

より多くのコードを見ずに私はより確信することはできません。

于 2011-07-27T18:18:59.897 に答える