gpt4 book ai didi

c# - 使用自定义模型 Binder 时出现 NullReferenceException

转载 作者:行者123 更新时间:2023-11-30 18:41:24 25 4
gpt4 key购买 nike

我正在尝试为抽象类制作 Binder 。 Binder 决定使用哪个类的实现。

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."; } }
}

所以我有一个带宠物的 Controller , Binder 决定(取决于物种字符串)它是狗、猫还是牲畜。

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(在 PetBinder 中的 var name = (string)values.GetValue("name").ConvertTo(typeof(string));
行)。我做错了什么?

我添加了一个 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> , 但当在 Person它们被命名为 pet.name 的对象和 pet.species当它们在单个 Pet 中时, 它们只是命名为 namespecies .

解决方案

[n] 获取具有正确前缀(petGetValue 或其他任何内容)的参数名称,我使用了以下代码:

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

如果有人感兴趣,我最终继承自 DefaultModelBinder使用与此类似的东西 answer .这是我使用的完整代码:

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
}

}

最佳答案

在您遇到错误的行中,values可以是 null 或什么 GetValue("name")返回可以为空。

我假设你调用 List<Pet>方法,ValueProvider 返回整个 List而不是每个人Pet , 所以它不能得到值 "name"因为它不存在于 List 中类。

如果没有看到更多代码,我无法确定。

关于c# - 使用自定义模型 Binder 时出现 NullReferenceException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6849043/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com