将对象(使用KeyValuePair)传递回控制器

时间:2012-07-23 21:14:35

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

我一直在寻找答案,但我一直都处在困境中,所以我认为这里的好人可以帮助我!

我有一个我在索引页面上列出的Monitor对象列表。每个监视器都有更多信息显示在详细信息页面上。我遇到的问题是

public List<KeyValuePair<int, int>> FaxcomMonitorData { get; set; }

如下所示。

监控类:

[DataContract]
public class Monitor
{
    [DataMember]
    public string MonitorType { get; set; }

    [DataMember]
    public string AtlasMonitorHeader { get; set; }

    [DataMember]
    public string AtlasMonitorData { get; set; }

    [DataMember]
    public List<KeyValuePair<int, int>> FaxcomMonitorData { get; set; }

    (...other attributes here...)

}

监视器有两种类型:ATLAS和FAXCOM。根据它们的不同,相应的数据属性将使用适当的值进行更新,另一个数据属性将保留为null。 (即Atlas的AtlasMonitorHeader和Data不为null,但FaxcomMonitorData为null)

Index ActionResult:

public ActionResult Index() 
    {
        MonitorServiceClient client = null;
        List<Monitor> monitors = null;
        try
        {
            client = new MonitorServiceClient("BasicHttpBinding_IMonitorService");
            monitors = new List<Monitor>(client.GetMonitors());
            if (monitors.Any(x => x.Status.Equals("red")))
                ViewData["OverallStatus"] = "red";
            else
                ViewData["OverallStatus"] = "green";
        }
        catch (Exception ex)
        {
            if (null != client)
                client.Abort();
        }
        return View(monitors);
    }

当显示器列表进入此处时,列表中的显示器看起来很棒! KeyValuePair具有正确的值,一切都很好。

索引视图:

<div id="overallstatus">
    <table style="border-style:none">
        <tr>
            <td style="vertical-align:middle; font-size:30px; color:Black; border-style:none" >Overall Status:</td>
            <td style="border-style:none" >
                <% if (ViewData["OverallStatus"].Equals("red")) { %>
                    <img src="../../../Content/Images/RedStoplightRG.png" alt="" height="60px" width="140px"/>
                <% } %>
                <% else if (ViewData["OverallStatus"].Equals("green")) { %>
                    <img src="../../../Content/Images/GreenStoplightRG.png" alt="" height="60px" width="140px"/>
                <% } %>
            </td>
        </tr> 
    </table>
</div>

<br />
<br />

<table>
    <tr>
        <th></th>
        <th>
            Monitor
        </th>
        <th>
            Current Status
        </th>
        <th>
            Last Update
        </th>
    </tr>

<% foreach (var item in Model) { %>
    <tr>
        <td>
            <%: Html.ActionLink("Details", "Details", item)%>
        </td>
        <td>
            <%: item.MonitorName %>
        </td>
        <td>
            <% if (item.Status.Equals("green")) { %>
                <img alt="" src="../../../Content/Images/GreenStoplightRG.png" height="40px" width="95px"/> 
            <% } %>
            <%-- <% else if (Model.CurrentStatus.Equals("red")) { %>
                <img alt="" src="../../../Content/Images/RedStoplightRG.png" />
            <% } %> --%>
            <% else { %>
                <img alt="" src="../../../Content/Images/RedStoplightRG.png" height="40px" width="95px"/>
            <% } %>
        </td>
        <td>
            <%: String.Format("{0:g}", item.LastUpdated) %>
        </td>
    </tr>

<% } %>

</table>

此处的底部表格显示每个监视器和一些数据。当我单击详细信息超链接时,我将转到此控制器方法。

详情ActionResult:

public ActionResult Details(Monitor monitor)
    {
        if (monitor.MonitorType.Equals("ATLAS"))
            return RedirectToAction("AtlasDetails", monitor);
        if (monitor.MonitorType.Equals("FAXCOM"))
            return RedirectToAction("FaxcomDetails", monitor);

        return RedirectToAction("Index");
    }

如果我点击ATLAS类型的监视器(没有KeyValuePair),所有属性都可以。

传真类型虽然正确设置了大部分属性,但KeyValuePair除外。它现在为null,即使它不是最初收到对象时(在Index ActionResult中)。

我不相信我正在做任何事情导致KeyValuePair在视图中变为null,但我之前没有使用它所以我可能需要以与我现在不同的方式传递信息。 / p>

如果其他代码或说明有帮助,请与我们联系。谢谢!

编辑:我根本没有使用数据库,我在索引页面中使用的服务只会给我一个Monitor对象列表。我宁愿不再打电话(等待)这项服务,因为如果有很多监视器需要很长时间。

编辑: 感谢fan711对我们尝试的原因不起作用的解释,由于时间限制,我们决定采用不同的(有些难看的)解决方法。如果你有更多的时间,你应该采用Jonathan的答案,并尽可能遵循这些良好的编码实践。我想我至少会在这里发布我们所做的事情以防其他人想要使用它。

我们最终使FaxcomMonitorData成为一个由逗号和胡萝卜(和^)分隔的字符串,以将键与其值和键值与其他键值分开。然后我们解析了这个字符串并将数据存储在List&gt;中。

List<KeyValuePair<int,int>> FaxcomData = new List<KeyValuePair<int,int>>();

        List<string> keyvaluepairs = monitor.FaxcomMonitorData.Split('^').ToList();
        foreach (var pair in keyvaluepairs)
        {
            List<string> stringData = pair.Split(',').ToList();
            FaxcomData.Add(new KeyValuePair<int,int>(Convert.ToInt32(stringData[0]), Convert.ToInt32(stringData[1])));
        }

感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

不是通过整个“监视器”对象,也许最好通过一个Id,并在Details操作中重建对象?

答案 1 :(得分:1)

ActionLink()的第三个参数是你的情况RouteValues。您无法将复杂对象传递给此参数;它是路由值的键/值集合。您可以在第一个视图的结果html中看到在item-object的每个属性上都返回.ToString。

正如Jonathan所说,首选方法是从服务中重新加载监视器对象。如果这不可能,您可能希望将整个对象包装在一个表单中,并将每个属性作为隐藏字段传递。类似的东西:

<% for (item = 0; item<Model.Count; item++) { %>
    <% using(Html.BeginForm("Details",Nothing, FormMethod.Post)) { %>
        <%= Html.HiddenFor(m => m(item).MonitorType) %>
        <%= Html.HiddenFor(m => m(item).AtlasMonitor) %>
        <%= Html.HiddenFor(m => m(item).AtlasMonitorData) %>
        <% for (var i = 0; i<item.FaxcomMonitorData.Count; i++) { %>
            <% Html.HiddenFor(Function(m) m(item).Data(i).Key) %>
            <% Html.HiddenFor(Function(m) m(item).Data(i).Value) %>
        <% } %>
        <input type="submit" value="Search" />
    <% } %>
<% } %>

您可能需要将项目放在局部视图中(不测试此代码)。这可能听起来很复杂,但MVC并非旨在将对象从控制器操作传递到控制器操作。

我能想到的另一个解决方案是将监视项目存储在会话状态中。然后只将索引传递给'Details'操作方法。从会话状态检索回来。这当然会增加通常不推荐的状态。