www update tools packs net mvc4 mvc language instalar asp c# asp.net-mvc asp.net-mvc-3 internet-explorer razor

c# - update - mvc 4+



Comportamiento inesperado de IE9 con MVC, etiqueta IMG, Url.Action y TempData (3)

No estoy seguro de por qué IE9 está solicitando la imagen dos veces, pero tengo un consejo que puede ayudar y sentir menos hackarific:

Está generando la imagen de gráfico cuando se procesa el HTML, en lugar de cuando se solicita realmente la imagen. Si cambió su acción RenderChart para aceptar el parámetro de color y luego renderizar la imagen, sin usar TempData, varias cosas serían más fáciles:

  • Su método RenderAction ya no se basa en el almacenamiento de SessionState para la imagen TempData
  • Esto hace que RenderAction sea más fácil de probar
  • Esto elimina la suposición de que la llamada a / Chart / RenderChart desde la etiqueta img definitivamente será desde la página correcta (es un escenario de enrutamiento de mayúsculas y minúsculas, seguro, pero es posible)
  • La aplicación de un OutputCache corto a RenderAction evitaría que se generen varias imágenes por duplicado para el mismo color dentro del período de almacenamiento en caché, incluso si se solicitan dos veces

Dado que la URL de la imagen ahora es más RESTful, es decir, el único identificador de recursos identifica el recurso único, en lugar de confiar en un valor TempData oculto, también puede cambiar su formulario para que sea una solicitud GET, evitando la alerta de navegador "formulario de reenvío" , o incluso podría simplemente cambiar el img src a través de javascript y eliminar el formulario por completo.

Saqué esto a un lado cuando me topé por primera vez con este problema. Pregunta anterior , no podía identificarlo en mi aplicación porque había demasiados javascript, css e imágenes dando vueltas que podrían haber agravado el problema.

Ahora he hecho una aplicación MVC muy simple sin javascipt, sin CSS y sin otras imágenes, y parece que IE9 llama a mi Url.Action dos veces (el violinista lo confirma), pero tanto Chrome como Firefox hacen lo que yo esperaba.

La aplicación es simple, contiene un modelo que tiene una propiedad y un método que devuelve un flujo de memoria (de una imagen MSChart). La vista muestra la imagen y un selector de color, cuando la vista se publica en el controlador, el controlador establece el color para el gráfico y crea la vista. La imagen del gráfico se muestra llamando a una acción del controlador RenderChart través de Url.Action , el MemoryStream se pasa de la vista a la acción TempData través de TempData . Esto funciona bien para un GET, pero cuando es un POST IE9 siempre solicita RenderChart dos veces y la segunda vez, TempData ha sido eliminado. El problema puede resolverse "restableciendo" TempData en la acción RenderChart (línea comentada) pero es tan hackariffic que claramente no es una respuesta en la que confíes.

No busco alternativas. Ya tengo alternativas, pero ... ¿alguien puede explicar este comportamiento?

Aquí está el modelo

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

Aquí está la vista

@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" /> }

Y aquí está el controlador

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

Y el HTML resultante parece ... (lista de colores truncada)

<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>

Y la salida de Fiddler se ve así Fiddler cuando funciona (en modo compatibilidad)

Encabezado Fiddler: funciona bien

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,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 Cookie: ASP.NET_SessionId=biv2pyhxucudsg3aqsvv3jbs

Fiddler Header Failure

GET /Chart/Index/Transparent HTTP/1.1 Accept: text/html, application/xhtml+xml, */* Referer: http://localhost:54307/Chart/Index/WindowFrame 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/Transparent 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 Cookie: ASP.NET_SessionId=biv2pyhxucudsg3aqsvv3jbs

Y aquí hay algunos tiempos para fiddler (post / imageOK / image failed)

Tenga en cuenta que el error no se inicia hasta mucho después de que se complete la publicación. me hace preguntarme si no hay algún tipo de hilo adicional en alguna parte que piense que la etiqueta IMG no se ha cumplido y decide ir y hacerlo. Misterio de hecho

== 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


Si su vista está copiada / pegada desde cuando estaba teniendo este problema, hay una coincidencia de } caracteres allí.

La razón por la cual esto es relevante es que Html.BeginForm se cierra antes y, de hecho, representará la etiqueta de cierre del elemento de form en el lugar equivocado (en el medio de su div ). Esto, a su vez, crea una situación HTML no válida donde el navegador necesita determinar el mejor curso de acción para analizar y construir un árbol DOM para mostrarle la página.

Internet Explorer (al menos versiones anteriores y modos de compatibilidad) en algunos casos resolvería esto al duplicar nodos en el DOM. Firefox, Chrome y Safari hacen las cosas un poco más inteligentes / diferentes.

Podría ser que el resultado que estás viendo se deba a que IE está creando dos elementos <img> en su DOM y luego solicita la imagen dos veces desde tu script.

Esto podría confirmarse abriendo la página en IE9, presionando F12 para abrir Herramientas de desarrollo y luego navegando en el DOM buscando un <img> adicional.


Tuvimos exactamente el mismo problema coincidiendo con los Gráficos, solo la diferencia fue la nuestra personalizada, pero basada en MSChart. Ahora hacemos lo siguiente, utilizando un resultado de contenido de archivo en lugar de un resultado de acción

Controlador:

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

Ver:

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

Espero que esto ayude

EDITAR:

¡Me acabo de dar cuenta de que está llamando al servidor en su conjunto de TempData!

eliminar esta línea de su vista:

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

y cambie su RenderChart para hacer lo siguiente:

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

La razón es que, cuando estás renderizando tu vista, llamas al método en la etiqueta Img, pero también la llamas cuando configuras los datos temporales :

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

Por lo tanto, invocar el método de gráfico dos veces. Espero que esto ayude :)