0

Is there a filter or some other mechanism in ASP.NET MVC Core where I can evaluate the property and value of the model before the View is rendered? I'm annotating some properties of my model and I need to translate their value before the model is rendered in the View.

I tried using the 'IDisplayMetadataProvider' but this only works if the model properties are part of a model expression. In my case, they aren't -- they are often used just for display purposes (like the ViewBag.Title for instance).

Simple example:

public class MyModel
{
  [Translate]
  public string TitleKey { get; set; }
  public string SomeOtherProp {get;set;}
  public int AnotherProp {get;set;}
}

public class MyController
{
  [HttpGet]
  public IActionResult Index()
  {
     var vm = _service.GetViewModel();

     vm.TitleKey = "Title.Translation.Key";

     return View(vm);
  }
}

Before the model is rendered in the View, I need to have some way of inspecting the model and finding which properties are annotated with "Translate". If they are, then get the value of that property and change it to something else. In this example I want to get the value of the "TitleKey" property, call a translation service to translate that value, then reassign that value before it hits the View.

Jake Shakesworth
  • 3,335
  • 4
  • 29
  • 43
  • Yes potentially but can you include a snippet of what you are trying to do? – Brian Mains Nov 03 '17 at 20:32
  • There is already a recommended pattern from Microsoft for [Globalization and localization in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/localization) – Erik Philips Nov 03 '17 at 21:02
  • Unfortunately, I can't use the built-in support for localization. What I'm working with is highly customized and doesn't use resx files. Granted, it may be possible to override some behavior to make it work but, for now, all I really need is a way to evaluate those properties and my job is done. – Jake Shakesworth Nov 03 '17 at 21:17

2 Answers2

1

the answer might not be exactly what you are looking for, but, I think you want to take a look at action filters in aspnet core

Action filters

They give you 2 methods:

  1. OnActionExecuting

  2. OnActionExecuted

From your description looks like you would like to manipulate the input to OnActionExecuted. You will need to test this properly as Action Filters might might not get called in case some other filter decided to short circuit the pipeline or if response has already started.

Muqeet Khan
  • 2,094
  • 1
  • 18
  • 28
1

You can get value from custom attribute-decorated property and do:

private void Translate(object o)
{
    var t = o.GetType();
    var props = t.GetProperties();
    foreach (var prop in props)
    {
        var propattr = prop.GetCustomAttributes(false);
        var shouldTranslate = propattr.Any(row => row.GetType() == typeof(TranslateAttribute));
        if (shouldTranslate)
        {
            var value = (string)prop.GetValue(o, null);
            if (value != null)
            {
                prop.SetValue(o, MyTranslationService(value));
            }
        }
    }
}

private String MyTranslationService(String s)
{
    return s + " :)";
}

Usage:

public IActionResult Index()
{
    var vm = _service.GetViewModel();

    vm.TitleKey = "Title.Translation.Key";

    Translate(vm);
    return View(vm);
}

You could even override View to call Translate method.

aaron
  • 39,695
  • 6
  • 46
  • 102
  • This will work for simple objects, but it's possible I could have complex objects with deeply nested types. I can achieve something similar with the Asp.Net webAPI by creating a custom json contract resolver that easily allows one to inspect properties of all objects passing through the pipeline. Ideally I would like to do something similar in MVC. – Jake Shakesworth Nov 29 '17 at 02:18
  • My answer addresses this question. Please ask a new question by clicking the [Ask Question](https://stackoverflow.com/questions/ask) button. Include your comment above and related code. Include a link to this question if it helps provide context. – aaron Nov 29 '17 at 02:24