ExtJS 의 store. sync 가 Asp. net MVC 의 Action 에 제출 할 때 System. Reflection. AmiguousMatchException 이상 을 일 으 킵 니 다.

9521 단어
ExtJs 의 store 는 sync 에 있 을 때 데 이 터 를 대량으로 제출 할 수 있 습 니 다. 대량 이란 store 에 create, update, delete 의 대상 을 동시에 기록 할 때 세 번 에 나 누 어 제출 하 는 것 을 말 합 니 다.제출 할 때 여러 대상 이 JSON 형식의 문자열 로 조 합 됩 니 다. 제출 할 데이터 가 하나 일 때 JSON 의 문자열 은 다음 과 같 습 니 다.
{"ID":"a6d671ca-5480-4b5b-bf7a-b8459c0f598b","MobilePIN":"","Email":"[email protected]","Password":"","CreateDate":null,"LastLoginDate":null,"LastPasswordChangedDate":null,"Comment":"","UserName":"user1","MobileAlias":"","LastActivityDate":null,"DisplayName":"","RememberMe":false}

여러 데이터 일 때 JSON 의 문자열 은:
[{"ID":"a6d671ca-5480-4b5b-bf7a-b8459c0f598b","MobilePIN":"","Email":"[email protected]","Password":"","CreateDate":null,"LastLoginDate":null,"LastPasswordChangedDate":null,"Comment":"","UserName":"user1","MobileAlias":"","LastActivityDate":null,"DisplayName":"","RememberMe":false}]

Controller 의 Action 에서 방법의 서명 이 Public Json Result Create User (UserDataObject user) 라면 여러 데이터 가 들 어 올 때 1 조 만 받 을 수 있 습 니 다.방법 서명 이 private List < UserDataObject > ProcessUsers (List < UserDataObject > users) 일 때 여러 개의 데이터 에 문제 가 없 지만 한 개의 데이터 만 있 을 때 users 는 null 값 입 니 다.
나 는 당연히 Action 에서 두 가지 방법 을 모두 쓰 고 싶 었 지만 결 과 는 System. Reflection. AmiguousMatchException, 즉 MVC 의 Action Selector 는 어떤 방법 을 바 꿔 야 할 지 구분 할 수 없 었 다.
MVC 코드 를 찾 아 보면 AsyncAction MethodSelector 의 RunSelection Filters 방법 에서 Action 에 있 는 Atrribute 를 찾 을 수 있 습 니 다. HttpPost 와 같은 Attribute 는 현재 호출 된 컨 텍스트 에 맞 는 지 여 부 를 판단 하기 위해 여과 합 니 다.
이 점 을 알 게 된 후에 저 는 사용자 정의 Attribute 를 작성 한 다음 에 현재 Request 가 요청 한 내용 에 따라 어떤 방법 을 사용 할 수 있 는 지, 어떤 방법 을 사용 할 수 없 는 지 결정 할 수 있 습 니 다. 이 를 실현 하 는 관건 은 두 가지 가 있 습 니 다.
1. 이 Attribute 를 어떻게 실현 합 니까?
2. Request 의 Post 내용 을 어떻게 얻 고 해결 합 니까?
 
첫 번 째 문 제 는 잘 해결 되 었 습 니 다. 저 는 MVC 방면 의 자 료 를 체계적으로 보지 못 했 기 때문에 HttpPost 를 보면 Action MethodSelector Attribute 를 계승 했다 는 것 을 알 수 있 습 니 다. 이런 유형 에는 추상 적 인 방법 이 있 습 니 다. IsValid ForRequest.
두 번 째 문 제 는 Request 를 받 은 후 현재 Post 의 유형 이 application / json 인지 판단 하여 Post 의 데 이 터 를 JSON 의 역 직렬 화 할 수 있 습 니 다.테스트 를 통 해 알 수 있 듯 이 단일 대상 이 라면 반 직렬 화 대상 은 Dictionay < String, Object > 대상 이 고 여러 대상 은 Object [] 를 얻 었 다.다음 에 실 현 된 소스 코드 를 드 립 니 다.
public class JsonModelPostAttribute : ActionMethodSelectorAttribute
    {
        public enum ParameterType
        {
            Single,
            Multiple
        }

        private ParameterType _parameterType;
        public ParameterType MethodParameterType
        {
            get
            {
                return _parameterType;
            }
            set
            {
                _parameterType = value;
            }
        }

        public JsonModelPostAttribute()
        {
            _parameterType = ParameterType.Single;
        }

        public JsonModelPostAttribute(ParameterType type)
        {
            _parameterType = type;
        }

        public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
        {
            var c = GetDeserializedObject(controllerContext);            
            if (c == null)
            {
                return true;
            }
            if (MethodParameterType == ParameterType.Single)
            {
                return c is Dictionary<string, object>;
            }
            else
            {
                return c is object[];
            }
        }

        private static object GetDeserializedObject(ControllerContext controllerContext)
        {
            if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
            {
                // not JSON request
                return null;
            }

            controllerContext.HttpContext.Request.InputStream.Seek(0, SeekOrigin.Begin);

            StreamReader reader = new StreamReader(controllerContext.HttpContext.Request.InputStream);
            string bodyText = reader.ReadToEnd();

            controllerContext.HttpContext.Request.InputStream.Seek(0, SeekOrigin.Begin);

            if (String.IsNullOrEmpty(bodyText))
            {
                // no JSON data
                return null;
            }

            JavaScriptSerializer serializer = new JavaScriptSerializer();
            object jsonData = serializer.DeserializeObject(bodyText);
            return jsonData;
        }
    }

주의해 야 할 것 은 InputStream 을 읽 은 후에 Position 을 0 으로 다시 설정 해 야 합 니 다. 그렇지 않 으 면 후속 적 인 Json Value Provider Factory 는 역순 화 인 스 턴 스 를 얻 지 못 합 니 다. 그러면 정확 한 Action 에 들 어 갈 수 있어 도 매개 변 수 는 비어 있 습 니 다.
다음은 Controller 에서 테스트 한 코드 세 션 입 니 다.
        [AllowAnonymous]
        [HttpPost]
        [JsonModelPost(JsonModelPostAttribute.ParameterType.Multiple)]
        public JsonResult CreateUser(List<UserDataObject> users)
        {
            ProcessUsers(users);

            return this.Json(new { success = true, user = users }, JsonRequestBehavior.AllowGet);
        }

        private List<UserDataObject> ProcessUsers(List<UserDataObject> users)
        {
            int i = 1;
            foreach (var user in users)
            {
                user.ID = Guid.Empty.ToString();
                user.UserName = "Server Name" + i++;
            }
            return users;
        }

        [AllowAnonymous]
        [HttpPost]
        [JsonModelPost(JsonModelPostAttribute.ParameterType.Single)]
        public JsonResult CreateUser(UserDataObject user)
        {
            var list = new List<UserDataObject>(new UserDataObject[] { user });
            ProcessUsers(list);
            return this.Json(new { success = true, user = list[0] }, JsonRequestBehavior.AllowGet);
        }

좋은 웹페이지 즐겨찾기