微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – 使用MVC,IMG标记,Url.Action和TempData的IE9意外行为

当我第一次遇到这个问题 Previous Question时,我把它放在一边,我无法将它固定在我的应用程序中,因为有太多的javascript,css和图像踢可能会加剧问题.

现在我做了一个非常简单的MVC应用程序,没有javascipt,没有css,没有其他图像,似乎IE9调用了我的Url.Action两次(fiddler确认)但Chrome和Firefox都做了我期望的事情.

该应用程序很简单,它包含一个具有一个属性的模型和一个返回内存流(MSChart图像)的方法.视图显示图像和颜色选择器,当视图发布到控制器时,控制器设置图表的颜色并创建视图.通过Url.Action调用控制器RenderChart操作显示图表图像,MemoryStream通过TempData从视图传递到RenderImage操作.这适用于GET,但是当它是POST时,IE9总是请求RenderChart两次,第二次请求TempData已被删除.可以通过在RenderChart操作中重置“TempData”(注释掉的行)来解决这个问题,但这非常hackariffic,它显然不是你信任的答案.

我不是在寻找替代方案我已经有了替代方案但是……任何人都可以解释这种行为吗?

这是模型

public class ChartModel
    {
        public ChartModel()
        {
            this.ChartColor = Color.Green;
        }
        public ChartModel(Color color)
        {
            this.ChartColor = color;
        }
        public Color ChartColor { get; set; }
        public MemoryStream Chart()
        {
            Chart chart = new Chart();
            chart.Height = 250;
            chart.Width = 450;
            chart.ImageType = ChartimageType.Jpeg;
            chart.RenderType = RenderType.BinaryStreaming;
            chart.BackColor=ChartColor;

            chart.BorderlineDashStyle = ChartDashStyle.solid;
            chart.BackGradientStyle = GradientStyle.TopBottom;
            chart.Borderlinewidth = 2;
            chart.BorderlineColor = Color.Blue;
            chart.BorderSkin.SkinStyle = BorderSkinStyle.emboss;
            ChartArea ca = chart.ChartAreas.Add("Default");
            ca.BackColor = Color.Transparent;
            ca.AxisX.IsMarginVisible = false;

            Series series = chart.Series.Add("browser/Gets");
            series.ChartType = SeriesChartType.Bar;
            string[] browsers = new string[]{"IE9","Chrome","FireFox"};
            int[] gets = new int[]{2,1,1};
            series.Points.DataBindXY(browsers,gets);

            using (MemoryStream memStream = new MemoryStream())
            {
                chart.SaveImage(memStream,ChartimageFormat.Jpeg);
                return memStream;
            }
        }
    }

这是观点

@model TestChart.Models.ChartModel          
@{
    ViewBag.Title = "Chart";
}
<h2>Chart</h2>
@using (Html.BeginForm("Index","Chart"))
{
    @Html.DropDownListFor(m => m.ChartColor,new SelectList(Enum.GetNames(typeof(System.Drawing.KNownColor))))
    <br />
    <div>
        <div>
            <br />
            @{TempData["Chart"] = Model.Chart();
            }
            <img alt="Chart" src="@Url.Action("RenderChart","Chart")" />
        </div>
    </div>
    <input type="submit" value="Post" />
}

这是控制器

public class ChartController : Controller
    {
        public ActionResult Index( string colorName = "White")
        {
            ChartModel model;
            model = new ChartModel(Color.FromName(colorName));
            return View(model);
        }

        [HttpPost]
        public ActionResult Index(ChartModel model)
        {
            return RedirectToAction("Index",new { colorName = model.ChartColor.Name });
        }

        public FileContentResult RenderChart()
        {
            MemoryStream ms = TempData["Chart"] as MemoryStream;
            // TempData["Chart"] = ms; //uncomment this line to get IE9 to work - odd indeed
            return File(ms.ToArray(),"image/jpeg");
        }
    }

生成的HTML看起来像……(颜色列表被截断)

<form action="/Chart" method="post">
<select data-val="true" data-val-required="The ChartColor field is required." id="ChartColor" name="ChartColor"> <option>ActiveBorder</option>
:
<option>MenuHighlight</option>
</select>    <br />
    <div>
        <div>
            <br />
            <img alt="Chart" src="/Chart/RenderChart" />
        </div>
    </div>
    <input type="submit" value="Post" />
</form>
</body>
</html>

fiddler输出看起来像这样

fiddler工作时(在兼容模式下)

提琴手标题 – 工作正常

GET /Chart/Index/WindowFrame HTTP/1.1
Accept: text/html,application/xhtml+xml,*/*
Referer: http://localhost:54307/Chart/Index/Menu
Accept-Language: zh,es;q=0.9,en-GB;q=0.7,de-DE;q=0.6,fr-FR;q=0.4,nl;q=0.3,fr-CA;q=0.1
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
Accept-Encoding: gzip,deflate
Host: localhost:54307
Connection: Keep-Alive
Pragma: no-cache
Cookie: ASP.NET_SessionId=biv2pyhxucudsg3aqsvv3jbs

GET /Chart/RenderChart HTTP/1.1
Accept: image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5
Referer: http://localhost:54307/Chart/Index/WindowFrame
Accept-Language: zh,deflate
Host: localhost:54307
Connection: Keep-Alive
Cookie: ASP.NET_SessionId=biv2pyhxucudsg3aqsvv3jbs

提琴手头部失败

GET /Chart/Index/Transparent HTTP/1.1
Accept: text/html,*/*
Referer: http://localhost:54307/Chart/Index/WindowFrame
Accept-Language: zh,*/*;q=0.5
Referer: http://localhost:54307/Chart/Index/Transparent
Accept-Language: zh,deflate
Host: localhost:54307
Connection: Keep-Alive
Cookie: ASP.NET_SessionId=biv2pyhxucudsg3aqsvv3jbs

这里是小提琴手的一些时间(post / imageOK / image失败)

请注意,失败的那个在帖子完成之后才开始.让我想知道是否有某种额外的线程认为img标签尚未完成并决定去做.确实很神秘.

== FLAGS ==================
BitFlags: [None] 0x0
X-RESPONSEBODYTRANSFERLENGTH: 5627
X-PROCESSINFO: iexplore:3100
X-CLIENTIP: 127.0.0.1
X-HOSTIP: ::1
X-EGREsspORT: 62803
X-CLIENTPORT: 62801

== TIMING INFO ============
ClientConnected:    21:23:58.866
ClientBeginRequest: 21:23:58.866
ClientDoneRequest:  21:23:58.867
Determine Gateway:  0ms
DNS Lookup:         0ms
TCP/IP Connect: 1ms
HTTPS Handshake:    0ms
ServerConnected:    21:23:58.868
fiddlerBeginRequest:    21:23:58.868
ServerGotRequest:   21:23:58.868
ServerBeginResponse:    21:23:58.928
ServerDoneResponse: 21:23:58.928
ClientBeginResponse:    21:23:58.928
ClientDoneResponse: 21:23:58.928

== FLAGS ==================
BitFlags: [None] 0x0
X-RESPONSEBODYTRANSFERLENGTH: 17612
X-PROCESSINFO: iexplore:3100
X-CLIENTIP: 127.0.0.1
X-HOSTIP: ::1
X-EGREsspORT: 62804
X-CLIENTPORT: 62802

== TIMING INFO ============
ClientConnected:    21:23:58.866
ClientBeginRequest: 21:23:59.001
ClientDoneRequest:  21:23:59.001
Determine Gateway:  0ms
DNS Lookup:         0ms
TCP/IP Connect: 0ms
HTTPS Handshake:    0ms
ServerConnected:    21:23:59.002
fiddlerBeginRequest:    21:23:59.002
ServerGotRequest:   21:23:59.002
ServerBeginResponse:    21:23:59.012
ServerDoneResponse: 21:23:59.012
ClientBeginResponse:    21:23:59.012
ClientDoneResponse: 21:23:59.012

== FLAGS ==================
BitFlags: [None] 0x0
X-RESPONSEBODYTRANSFERLENGTH: 7996
X-PROCESSINFO: iexplore:3100
X-CLIENTIP: 127.0.0.1
X-HOSTIP: ::1
X-EGREsspORT: 62807
X-CLIENTPORT: 62805

== TIMING INFO ============
ClientConnected:    21:23:59.062
ClientBeginRequest: 21:23:59.063
ClientDoneRequest:  21:23:59.063
Determine Gateway:  0ms
DNS Lookup:         0ms
TCP/IP Connect: 0ms
HTTPS Handshake:    0ms
ServerConnected:    21:23:59.063
fiddlerBeginRequest:    21:23:59.063
ServerGotRequest:   21:23:59.064
ServerBeginResponse:    21:24:01.597
ServerDoneResponse: 21:24:01.597
ClientBeginResponse:    21:24:01.597
ClientDoneResponse: 21:24:01.598

解决方法

我们在使用图表的同时遇到了完全相同的问题,唯一的区别是我们的自定义,但基于MSChart.我们现在使用文件内容结果而不是操作结果执行以下操作

控制器:

public FileContentResult GetGraph(int id)
{
    var image = Resolve<CountryModel>().Load(id).Graph; //gets our Bitmap object
    image.Save(HttpContext.Response.OutputStream,ImageFormat.Jpeg);
    var converter = new ImageConverter();

    return new FileContentResult((byte[])converter.ConvertTo(image,typeof(byte[])),"image/jpeg");
}

视图:

<img src="@Url.Action("GetGraph","Country",new {Id = Model.CountryId})" />

希望这可以帮助

编辑:

我刚刚意识到你在TempData集中调用了服务器!

从您的视图中删除此行:

@{TempData["Chart"] = Model.Chart();

并更改您的RenderChart以执行以下操作:

public FileContentResult RenderChart()
{         
    return File(new ChartModel().Chart().ToArray(),"image/jpeg");
}

原因是,当您实际渲染视图时,您正在调用Img标记中的方法,但您在设置临时数据时也调用它:

@{TempData["Chart"] = Model.Chart();

从而调用图表方法两次.希望这可以帮助 :)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐