1

我试图四处寻找答案,但我已经被困了一天的大部分时间,所以我认为这里的好人可能能够帮助我!

我有一个在索引页面上列出的 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...)

}

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

索引操作结果:

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>

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

详细操作结果:

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),所有属性都很好。

尽管 FAXCOM 类型的大多数属性设置正确,但 KeyValuePair 除外。现在它为空,即使最初接收对象时不是(在索引 ActionResult 中)。

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

让我知道其他代码或解释是否会有所帮助。谢谢!

编辑:我根本没有使用数据库,我在索引页面中使用的服务只会给我一个 Monitor 对象列表。我不希望再次调用(并等待)该服务,因为如果有很多监视器会花费很长时间。

编辑:感谢 fan711 解释了为什么我们尝试的方法行不通,由于时间限制,我们决定采用不同的(有些丑陋的)解决方法。如果您有更多时间,您应该选择 Jonathan 的答案,并尽可能遵循这些良好的编码实践。我想我至少会在这里发布我们所做的,以防其他人想要使用它。

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

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])));
        }

感谢您的帮助!

4

2 回答 2

2

与其通过整个“监视器”对象,不如通过一个 Id 并在 Details 操作中重建对象会更好?

于 2012-07-23T21:25:54.933 回答
1

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

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

<% 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 并非旨在将对象从控制器动作传递到控制器动作。

我能想到的另一个解决方案是将监控项存储在会话状态中。然后仅将索引传递给“详细信息”操作方法。从会话状态中检索它。这当然会添加通常也不推荐的状态。

于 2012-07-24T05:15:12.517 回答