razor view with anonymous type model class. It is possible?
I want to create a view using razor template, but I do not want to write a class for model, because in many views i will have many queries which will be returning diferent models.
For example I have a linq query:
from p in db.Articles.Where(p => p.user_id == 2)
select new
{
p.article_id,
p.title,
p.date,
p.category,
/* Additional parameters which arent in Article model */
};
I need to write a View for this query. This query returns a Articles.
Now I dont know how should looks like a model definition.
I tried to use this deffinition:
@model System.Collections.IEnumerable
But then I had an erros than fileds doesnt exists in object type:
*CS1061: 'object' does not contain a definition for 'addition_field' and no extension method 'additio开发者_如何转开发n_field' accepting a first argument of type 'object' could be found*
This is my model for which I do not want to write a next model. Of course
The short answer is that using anonymous types is not supported, however, there is a workaround, you can use an ExpandoObject
Set your model to
@model IEnumerable<dynamic>
Then in the controller
from p in db.Articles.Where(p => p.user_id == 2)
select new
{
p.article_id,
p.title,
p.date,
p.category,
/* Additional parameters which arent in Article model */
}.ToExpando();
...
public static class Extensions
{
public static ExpandoObject ToExpando(this object anonymousObject)
{
IDictionary<string, object> anonymousDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(anonymousObject);
IDictionary<string, object> expando = new ExpandoObject();
foreach (var item in anonymousDictionary)
expando.Add(item);
return (ExpandoObject)expando;
}
}
The simplest solution if you are using C# 7.0+ (introduced in Visual Studio 2017+) is to use a tuple rather than an anonymous type.
Razor View: "_MyTupledView.cshtml"
@model (int Id, string Message)
<p>Id: @Model.Id</p>
<p>Id: @Model.Message</p>
Then when you bind this view, you just send a tuple:
var id = 123;
var message = "Tuples are great!";
return View("_MyTupledView", (id, message))
I think this is an even better solution:
http://buildstarted.com/2010/11/09/razor-without-mvc-part-iii-support-for-nested-anonymous-types/
This allows for nested anonymous types, which the aforementioned expando-object solution won't handle.
It seems you can't pass anonymous types but if you just want the values of the type you might pass an enumerable of an object array to view.
View:
@model IEnumerable<object[]>
@{
ViewBag.Title = "Home Page";
}
<div>
<table>
@foreach (var item in Model)
{
<tr>
<td>@item[0].ToString()</td>
<td>@item[1].ToString()</td>
</tr>
}
</table>
</div>
Controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
namespace ZZZZZ
{
public class HomeController : Controller
{
public ActionResult Index()
{
List<object[]> list = new List<object[]> { new object[] { "test1", DateTime.Now, -12.3 } };
return View(list);
}
}
}
精彩评论