ASP의 이유Net MVC 모델 바인더가 빈 JSON 배열을 null로 바인딩합니까?
모델 클래스는 다음과 같습니다.
public class MyModel
{
public Employees[] MyEmpls{get;set;}
public int Id{get;set;}
public OrgName{get;set;}
}
다음 JSON 구조 오브젝트 전달:MyEmpls as empty array
MVC 컨트롤러에 접속합니다.
["Id":12, "MyEmpls":[], "OrgName":"Kekran Mcran"]
컨트롤러
[HttpPost]
public ActionResult SaveOrg(MyModel model)
{
//model.MyEmpls is null here
}
임신했어요.mode.MyEmpls
null이 아닌 빈 c# 배열이어야 합니다.빈 어레이를 실현하기 위해 커스텀 모델 바인더가 필요합니까?
다른 답변 중 일부는 질문의 의미를 놓쳤다고 생각합니다.기본 MVC 모델바인더가 빈 Json 어레이를 빈 C# 어레이가 아닌 null로 바인드하는 이유는 무엇입니까?
왜 그랬는지는 말할 수 없지만 어디서 그런 일이 일어나는지 보여 줄 수는 있어MVC의 소스는, 다음의 CodePlex 로 입수할 수 있습니다.찾으시는 파일은 ValueProviderResult.cs 입니다.여기서 확인할 수 있습니다.
private static object UnwrapPossibleArrayType(CultureInfo culture, object value, Type destinationType)
{
if (value == null || destinationType.IsInstanceOfType(value))
{
return value;
}
// array conversion results in four cases, as below
Array valueAsArray = value as Array;
if (destinationType.IsArray)
{
Type destinationElementType = destinationType.GetElementType();
if (valueAsArray != null)
{
// case 1: both destination + source type are arrays, so convert each element
IList converted = Array.CreateInstance(destinationElementType, valueAsArray.Length);
for (int i = 0; i < valueAsArray.Length; i++)
{
converted[i] = ConvertSimpleType(culture, valueAsArray.GetValue(i), destinationElementType);
}
return converted;
}
else
{
// case 2: destination type is array but source is single element, so wrap element in array + convert
object element = ConvertSimpleType(culture, value, destinationElementType);
IList converted = Array.CreateInstance(destinationElementType, 1);
converted[0] = element;
return converted;
}
}
else if (valueAsArray != null)
{
// case 3: destination type is single element but source is array, so extract first element + convert
if (valueAsArray.Length > 0)
{
value = valueAsArray.GetValue(0);
return ConvertSimpleType(culture, value, destinationType);
}
else
{
// case 3(a): source is empty array, so can't perform conversion
return null;
}
}
// case 4: both destination + source type are single elements, so convert
return ConvertSimpleType(culture, value, destinationType);
}
}
흥미로운 부분은 "케이스 3"입니다.
else
{
// case 3(a): source is empty array, so can't perform conversion
return null;
}
모델의 생성자에 있는 어레이를 초기화하면 이 문제를 피할 수 있습니다.소스를 빠르게 읽어보면 빈 어레이를 반환할 수 없는 이유나 반환하지 않기로 결정한 이유를 설명할 수 없지만 흥미로운 읽을거리가 될 것입니다.
이것은 C#의 참조 타입의 디폴트값이기 때문에 null 값은 C#의 참조 유형에 대한 기본값입니다.빈 어레이를 가져오려면 컨스트럭터를 사용하여 모델 내의 어레이를 초기화해야 합니다.그러나 초기화할 때 어레이 크기를 정의해야 하므로 다음과 같은 다른 유형의 수집을 사용하는 것이 좋습니다.List
:
public class MyModel
{
public List<Employees> MyEmpls{get;set;}
public int Id{get;set;}
public OrgName{get;set;}
public MyModel()
{
MyEmpls = new List<Employees>();
}
}
빈 배열이 json에서 전달되면 빈 목록이 나타납니다.
어레이를 사용할 필요가 있는 경우는, 다음의 사이즈로 초기화해 주세요.
public class MyModel
{
public Employees[] MyEmpls{get;set;}
public int Id{get;set;}
public OrgName{get;set;}
public MyModel()
{
MyEmpls = new Employees[/*enter size of array in here*/];
}
}
모델을 받는다면.MyEmpls를 null로 하면 서버 측에서 다음과 같은 예외 발생을 중지하는 조건을 만들 수 있습니다.
if(model.MyEmpls !=null){
...
}
MyEmpls는 커스텀클래스 어레이로 []만 송신하고 있기 때문에 무효가 됩니다.
도움이 되시길 바랍니다.
다음과 같이 모델 바인더를 작성합니다.
public class MyModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
try
{
var request = controllerContext.HttpContext.Request;
return new MyModel
{
MyEmpls = request[] ?? new Employees[0],
Id = request["Id"] ?? "",
OrgName = request["OrgName"] ?? ""
};
}
catch
{
//do required exception handling
}
}
}
Application_Start에서 모델 바인더를 등록합니다.
ModelBinders.Binders.Add(typeof(MyModel), new MyModelBinder())
그리고 컨트롤러를 다음과 같이 수정합니다.
[HttpPost]
public ActionResult SaveOrg([ModelBinder(typeof(MyModelBinder))] MyModel model)
{
//model.MyEmpls is null here
}
값이 null인지 아닌지를 체크하는 세터를 정의할 수 있습니다.
public class MyModel
{
private _myEmpls{get;set;}
public Employees[] MyEmpls{
get{return _myEmpls;}
set{_myEmpls=(value==null?new List<Employees>():value);}
}
public int Id{get;set;}
public OrgName{get;set;}
}
[HttpPost]
public ActionResult SaveOrg(MyModel model)
{
var serializer = new JavaScriptSerializer();
var stream = System.Web.HttpContext.Current.Request.InputStream;
var reader = new StreamReader(stream);
stream.Position = 0;
var json = reader.ReadToEnd();
model= serializer.Deserialize<MyModel>(json);
//model.MyEmpls is [] here
}
JavaScriptSerializer는 빈 어레이를 올바르게 역직렬화합니다.따라서 전달된 모델을 무시하고 입력 요청 스트림에서 재구성할 수 있습니다.아마 올바른 방법은 아닐 겁니다. 하지만 일단 수고를 덜면 됩니다.시스템을 참조해야 합니다.Web.Extensions.
C# 어레이 초기화의 기본 동작은 빈 어레이가 아니라 늘입니다.
따라서 빈 어레이를 전송한 경우 빈 어레이는 시작되지 않지만 기본 초기화는 null로 트리거됩니다.
다음 링크를 참조하십시오.http://www.dotnetperls.com/null-array
언급URL : https://stackoverflow.com/questions/23108272/why-does-the-asp-net-mvc-model-binder-bind-an-empty-json-array-to-null
'source' 카테고리의 다른 글
AngularJS Web API 위조 방지토큰 CSRF (0) | 2023.03.28 |
---|---|
문자열에 문자가 포함되어 있는지 확인합니다(Javascript/jquery). (0) | 2023.03.28 |
클린 URL을 가져오기 위한 NGINX 다시 쓰기 규칙 (0) | 2023.03.28 |
원본에서 .txt 파일을 가져오려면 어떻게 해야 합니까? (0) | 2023.03.28 |
스프링 데이터 JPA @NoRepositoryBean 인터페이스에 대해서 (0) | 2023.03.28 |