传递给控制器​​的List <t>发送空项

时间:2016-01-28 14:32:30

标签: c# asp.net asp.net-mvc

PartialView包含带有Foo的模型List<Bar>。每个Bar项都包含两个属性BarAstring)和BarB(十进制)。
我试图在部分视图中呈现图表,但为了工作,我需要在同一个Controller上调用一个动作并将结果传递给<img />元素。要渲染图表,我需要BarABarB的集合来格式化数据 所以我尝试这样的事情:

控制器

public void GenerateChart(List<Bar> model)
{
    var chart = new System.Web.Helpers.Chart(400, 200)
    .AddTitle("Title")
    .AddSeries(
        name : "name",
        xValue : model.Select(m => m.BarA).ToArray(),
        yValues : model.Select(m => m.BarB).ToArray())
    .Write();
}

部分视图

RouteValueDictionary rvd = new RouteValueDictionary();
for (int i = 0; i < Model.Bars.Count; ++i)
{ rvd.Add("model[" + i + "]", Model.Bars[i]); }

<img src="@Url.Action("GenerateChart", rvd)" />

这个问题是,即使模型对象包含它应该包含的三个项目,它们也是空的 我也尝试使用ViewBag,如​​下所示:

ViewBag.BarA = Model.Bars.Select(m => m.BarA).ToArray();
ViewBag.BarB = Model.Bars.Select(m => m.BarB).ToArray();

在控制器端使用

public void GenerateChart()
{
    var chart = new System.Web.Helpers.Chart(400, 200)
    .AddTitle("Title")
    .AddSeries(
        name : "name",
        xValue : ViewBag.BarA,
        yValues : ViewBag.BarB)
    .Write();
}

但两个数组都是null。我也尝试了一些不同的想法,但我无法获得所需的信息。

要三重检查(数据在视图中显示正常)数据是否正确,我改为:

@{
    string[] barAs = Model.Select(m => m.BarA).ToArray();
    decimal[] barBs = Model.Select(m => m.BarB).ToArray();
    ViewBag.BarAs = barAs; // this has 3 items with the expected data
    ViewBag.BarBs = barBs; // this also works
}
<img src="@Url.Action("GenerateChart")" />

string[] BarAs = ViewBag.BarAs; // this assigns null
decimal[] BarBs = ViewBag.BarBs; // this also assigns null

2 个答案:

答案 0 :(得分:2)

您似乎并不真正了解MVC的工作原理。我鼓励您花一些时间浏览http://asp.net/mvc的所有教程,以熟悉框架。也就是说,您似乎正试图接近很多这样的事情,就像您在Web窗体世界中一样。 MVC是一个完全不同的野兽。

首先,Html.Action无法返回完整的图像,因为它所做的只是将返回值转储到正在生成的HTML中,并且您无法直接嵌入二进制对象在HTML中。

其次,即使您可以,也不能将其用作src标记的imgsrc必须是一个字符串,即一个URL,指向图像的位置。

所以,为了实现这一目标。您将需要一个完整的操作,以图像形式返回正确的响应。然后,您只需将图片src链接到点击此操作的路线即可。

public ActionResult GenerateChart(List<Bar> model)
{
    var chart = new System.Web.Helpers.Chart(400, 200)
        .AddTitle("Title")
        .AddSeries(
            name : "name",
            xValue : model.Select(m => m.BarA).ToArray(),
            yValues : model.Select(m => m.BarB).ToArray())
    .GetBytes("jpeg");

    return File(chart, "image/jpeg");
}

然后,

<img src="@Url.Action("GenerateChart", new { model = rvd })" alt="" />

现在,您只需链接到网址即可。该URL映射到命中GenerateChart操作的路径,然后返回实际图像 - 就像直接链接到物理图像一样。现在,浏览器可以正确地将img标记呈现给页面。

答案 1 :(得分:1)

通过GET请求将复杂类型传递给操作在技术上很血腥,所以我不知道这个解决方案是否符合您的需求,您可以按照以下方法进行操作;

<强> Your action will recieve model as serialized string and you have to Deserialize it to your model

public ActionResult GenerateChart(string modelAsString)
{
    List<Bar> model = new List<Bar>();
    model = JsonConvert.DeserializeObject<List<Bar>>(modelAsString);

    var chart = new System.Web.Helpers.Chart(400, 200)
    .AddTitle("Title")
    .AddSeries(
        name: "name",
        xValue: model.Select(m => m.BarA).ToArray(),
        yValues: model.Select(m => m.BarB).ToArray())
    .GetBytes("jpeg");

    return File(chart, "image/jpeg");
}

<强> Then you need to call your action via querystring like ?modelAsString={jsonData} 我用来处理数据的示例网址:http://localhost:18681/Home/GenerateChart/?modelAsString=[{%22BarA%22:%22barAData%22,%22BarB%22:1.1},{%22BarA%22:%22barAData2%22,%22BarB%22:441.14},{%22BarA%22:%22barAData43%22,%22BarB%22:44.1}]

您应该通过序列化模型来创建<img>网址,这些网址已准备好您使用<img>的页面操作。

我测试了一个虚拟数据,你可以在下面看到输出; Dummy Example

PS:用于创建虚拟数据我使用了以下方法;

public ActionResult DummyData()
{
    List<Bar> model = new List<Bar>();
    model.Add(new Bar() { BarA = "barAData", BarB = 1.1m });
    model.Add(new Bar() { BarA = "barAData2", BarB = 441.14m });
    model.Add(new Bar() { BarA = "barAData43", BarB = 44.1m });
    return Json(model, JsonRequestBehavior.AllowGet);
}

我也想知道是否有更有效的方式通过获取请求来做到这一点。

希望这有帮助!