WebApiContrib.Formatting.Razor icon indicating copy to clipboard operation
WebApiContrib.Formatting.Razor copied to clipboard

What about Lists or IEnumerables?

Open oliverjanik opened this issue 10 years ago • 2 comments

How do I tell this formatter which view to use? Naming conventions don't work because it looks for "List`1.cshtml".

I can't really annotate IEnumerable<Report> with ViewAttribute.

And I can't use ViewResult since I rely on content negotiation to return proper media type.

I would suggest a per Action attribute. Or introduce smarter naming convention.

oliverjanik avatar Apr 02 '14 01:04 oliverjanik

If anyone comes across this I've overridden the convention if the type is IEnumerable<T>.

    public class WrappedViewLocator : IViewLocator
    {
        private readonly RazorViewLocator razor = new RazorViewLocator();

        public string GetView(string siteRootPath, IView view)
        {
            var itemType = GetEnumerableType(view.ModelType);
            if (itemType != null)
                view = new ReimplementedView(view.Model, view.ModelType, itemType.Name + "List");

            return razor.GetView(siteRootPath, view);
        }

        private static Type GetEnumerableType(Type type)
        {
            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
                return type.GetGenericArguments()[0];


            return type
                .GetInterfaces()
                .Where(intType => intType.IsGenericType && intType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
                .Select(intType => intType.GetGenericArguments()[0])
                .FirstOrDefault();
        }
    }

    public class ReimplementedView : IView
    {
        public ReimplementedView(object model, Type modelType, string viewName)
        {
            Model = model;
            ModelType = modelType;
            ViewName = viewName;
        }

        public object Model { get; private set; }
        public Type ModelType { get; private set; }
        public string ViewName { get; private set; }
    }

oliverjanik avatar Apr 02 '14 01:04 oliverjanik

Is this generally re-usable for all purposes? If so, would you mind adding this as a PR?

panesofglass avatar May 15 '14 20:05 panesofglass