2015-08-19 3 views
0

Я использовал, чтобы иметь действие обработки некоторых сложных JSON данные:Разбор сложных данных JSON в ActionFilter

[HttpPost, ValidateAntiForgeryToken] 
public ActionResult GetAdditionals(string pageIdentifier, 
    IEnumerable<HtmlPlaceHolder> htmlPlaceHolders, 
    IEnumerable<DataSource> dataSourceRequests) 

, который был вызван со стороны клиента, как это:

var requestData = { 
    pageIdentifier: 'test', 
    htmlPlaceHolders: getHtmlPlaceHolders(), 
    dataSourceRequests: getDataSourceRequests(), 
    __RequestVerificationToken: token 
}; 
$.post(url, $.toDictionary(requestData), resultHandler, "json"); 

Где htmlPlaceHolders и dataSourceRequests будет содержать массивы объектов, соответствующие классам, указанным в сигнатуре метода действия.

$ .toDictionary() используется для получения сложного объекта на сервере надлежащим образом.

Все было хорошо. Но теперь я хочу обработать одни и те же данные в ActionFilter. Таким образом, в OnActionExecuting Methode, я хочу, чтобы разобрать данные в NameValueCollection, содержащихся в filterContext.HttpContext.Request.Form где имена пар имя/значение выглядеть следующим образом:

pageIdentifier 
htmlPlaceHolders[0].ControlId 
htmlPlaceHolders[0].FunctionName 
htmlPlaceHolders[0].Parameter 
... 
... 
dataSourceRequests[0].Id 
dataSourceRequests[0].Src 

Теперь мне нужно знаю, как я могу восстановить IEnumerable<HtmlPlaceHolder> и IEnumerable<DataSource> из этого NameValueCollection, как это было для моего действия. До сих пор я не могу найти хороший способ добиться этого.

ответ

1

Для такого рода сценариев лучше использовать связующее устройство вместо фильтра действий. Рассмотрим это в качестве простого примера:

public class MyComplexBinder : IModelBinder 
{ 
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     // check type of the object you are going to bind with 
     // bindingContext.ModelType 
     // if you could generate this kind of object use 
     // controllerContext.HttpContext.Request.Form 
     // or anything else and return generated object 
     return GenerateMyComplexObject(controllerContext); 
    } 
} 

Затем вы можете использовать это связующее вещество, как это:

public string MyAction([ModelBinder(typeof(MyComplexBinder))]MyComplexType complexParameter) 
{ 
} 

Если вы думаете, что это выглядит некрасиво написать свой собственный атрибут модель связующего:

public class ComplexAttribute : CustomModelBinderAttribute 
{ 
    public override IModelBinder GetBinder() 
    { 
     return new MyComplexBinder(); 
    } 
} 

Тогда вы можете написать:

public string MyAction([Complex]MyComplexType complexParameter) 
{ 
} 

Вы можете также зарегистрировать модель связующие в качестве глобального связующего в Global.asax.cs:

protected void Application_Start() 
{ 
    // some codes here 

    ModelBinders.Binders.Add(typeof(MyComplexType),new MyComplexBinder()); 
} 
+0

Спасибо за ваш сложный ответ Сэма, но цель перемещения функциональности от действия к actionfilter было удалить действие. Весь контекст: GetAdditionals вызывается после почти каждого сообщения ajax, чтобы получить дополнительную информацию с сервера, которая не была предоставлена ​​в исходном ответе с сервера. Очень глупый раствор. Теперь модель изменяется, а лишний материал из GetAdditionals отправляется одним и тем же вызовом ajax. Я стандартизовал весь процесс, но я не хочу, чтобы сигнатура каждого действия была загромождена параметрами, которые были в GetAdditionals, таким образом, ActionFilter. – Moolie

+0

BTW, теперь я создал класс C#, который содержит все параметры вызова GetAdditionals, используйте 'JSON.stringify' для отправки объекта на сервер и восстановления объекта этого класса с помощью' JsonConvert.DeserializeObject () ' – Moolie

Смежные вопросы