Конвертируйте данные во время выполнения, используя привязку модели MVC - PullRequest
0 голосов
/ 05 июля 2018

Я создал функцию, которая принимает объект MethodBase и словарь именованных параметров, сопоставляет именованные параметры с методом и преобразует данные, чтобы метод можно было вызывать с правильными параметрами.

Чтобы преобразовать данные, которые я использовал

parameters[paramIndex] = Convert.ChangeType(item.Value, paramType);

Однако это не будет работать для связанных типов MVC, так как простой вызов объекта MethodBase не выполняет преобразование данных через привязки MVC.

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

if(ModelBinders.Binders.TryGetValue(paramType, out var binder)){...}

Однако я не уверен, как использовать связыватель для преобразования данных. Я пытался использовать этот ответ , но нет никакого объяснения того, что на самом деле являются параметрами ModelBindingContext и как их использовать для этих целей.

Context

Думал, что было бы разумно предоставить некоторый контекст: я пытаюсь сделать это, когда мы выполняем рендеринг SVG и HTML DOM на стороне сервера (используя Puppeteer / batik), но некоторые из DOM имеют встроенные изображения со ссылками в них .

Итак, перед выполнением рендеринга:

  • Поиск URL-адресов изображений из DOM
  • Разбор параметров и выход из маршрута
  • Найти метод для вызова в сборке через его атрибут маршрута MVC
  • Вызовите метод с преобразованными параметрами для рендеринга изображения.
  • Преобразовать результат в base64
  • Измените встроенное изображение в DOM, чтобы использовать представление base64, а не URL

Заранее спасибо за помощь.

Полное определение метода:

    private static object[] MapParameters(MethodBase method, IDictionary<string, object> namedParameters)
    {
        var parms = method.GetParameters();
        var paramNames = parms.Select(p => p.Name).ToArray();
        var parameters = new object[paramNames.Length];
        for (var i = 0; i < parameters.Length; ++i)
            parameters[i] = Type.Missing;

        foreach (var item in namedParameters)
        {
            var param = parms.First(parm => parm.Name == item.Key);
            var paramType = Nullable.GetUnderlyingType(param.ParameterType) ?? param.ParameterType;
            var paramName = item.Key;
            var paramIndex = Array.IndexOf(paramNames, paramName);

            if (ModelBinders.Binders.TryGetValue(paramType, out var binder))
            {
                // Use the binder to convert data
                continue;
            }

            parameters[paramIndex] = Convert.ChangeType(item.Value, paramType);
        }

        return parameters;
    }

1 Ответ

0 голосов
/ 06 июля 2018

Чтобы решить эту проблему, вы можете просто бросить фиктивные ControllerContext и ModelBindingContext в реализацию IModelBinder.BindModel, как показано ниже:

private static object ConvertDataWithModelBinder(IModelBinder binder, object value)
{
    const string modelName = "ValueToBeConverted";
    var modelContext = new ModelBindingContext { ModelName = modelName };
    var routeData = new RouteData { Values = { { modelName, value } } };
    var controllerContext = new ControllerContext { RouteData = routeData };
    return binder.BindModel(controllerContext, modelContext);
}

Предполагается, что реализация связывателя смотрит на объект ControllerContext.RouteData.Values (я проверил наши связующие модели, и они в основном это делают), однако некоторые из них также используют метод BindingContext.ValueProvider.GetValue для получения значения из контекста контроллера.

Возможно, вам также потребуется добавить фиктивную реализацию ValueProvider, содержащую один ValueProviderResult с указанным выше ModelName и значением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...