简体   繁体   English

如何处理IE9 html表错误,其中额外列显示部分视图的某些行?

[英]How to deal with IE9 html table bug where extra column shows up for some rows with partial view?

I see this question has already been asked around a IE9 but which is adding extra columns in random rows of a html table. 我看到这个问题已经在IE9周围被问到,但是在html表的随机行中添加了额外的列。 The root issue seems to be a IE 9 bug that is fixed in IE 10 (but i have a lot of IE9 users) 根问题似乎是在IE 10中修复的IE 9错误(但我有很多IE9用户)

It states it usually happens with tables built via ajax but i am seeing this on regular pages that output html tables. 它声明它通常发生在通过ajax构建的表中,但我在输出html表的常规页面上看到这一点。

There is a workaround Javascript solution but the answer assumes that you were building a table with Javascript (from an ajax call). 有一个解决方法Javascript解决方案,但答案假定您正在构建一个使用Javascript的表(来自ajax调用)。 I am using a partial view (or in some cases just rendering a regular formatted html table directly on a single page) so I wanted to find out if there is a solution to prevent this UI issue on IE9 when you are simply rendering direct html on page. 我正在使用局部视图(或者在某些情况下只是直接在单个页面上呈现常规格式化的html表)所以我想知道是否有一个解决方案可以在IE9上直接渲染直接html时阻止此UI问题页。

I want to avoid having to literally have no white space in my actually code as that will be very hard to maintain. 我想避免在我的实际代码中实际上没有空格,因为这将很难维护。

I faced this same problem and ended up on this page looking for a solution. 我遇到了同样的问题,最终在这个页面上寻找解决方案。 In my case the problem was with HTML rendered by a Repeater control with ASP.Net 4. 在我的情况下,问题是由ASP.Net 4的Repeater控件呈现的HTML。

I inspected the code generated by the server with Charles and there was no problem with the HTML. 我检查了服务器用Charles生成的代码,HTML没有问题。

The last sentence in the question lead me to my own simple solution. 问题的最后一句话引导我自己的简单解决方案。

I want to avoid having to literally have no white space in my actually code as that will be very hard to maintain. 我想避免在我的实际代码中实际上没有空格,因为这将很难维护。

I simply put comments between the opening of the TR tag and the first TD tag as well as between each TD and the closing TR tag: 我只是在TR标记的开头和第一个TD标记之间以及每个TD和结束TR标记之间添加注释:

<tr><!--
 --><td class="cell">
    Cell 1  
    </td><!--
 --><td class="cell">
    Cell 2  
    </td><!--
 --><td class="cell">
    Cell 3  
    </td><!--
 --><td class="cell">
    Cell 1  
    </td><!--
 --></tr>

This solution means we don't have to use an extension and it won't be hard to read or maintain the code in the future. 此解决方案意味着我们不必使用扩展,并且将来不难读取或维护代码。

This is possible. 这个有可能。 For partial views it's simpler, because you can capture the output of Html.Partial directly, modifying it before the response is written to the output stream. 对于部分视图,它更简单,因为您可以直接捕获Html.Partial的输出,在将响应写入输出流之前对其进行修改。

In order to do that, you'd create an extension method, which could look something like this: 为此,您需要创建一个扩展方法,它看起来像这样:

public static class HtmlExtensions
{
    public static HtmlString PartialIE9TableFix(this HtmlHelper helper,
        string view, object model = null)
    {
        var partialOutput = helper.Partial(view, model).ToString();
        partialOutput = Regex.Replace(partialOutput, @"/td>\s+<td",
                            "/td><td", RegexOptions.IgnoreCase);

        return MvcHtmlString.Create(partialOutput);
    }
}

As you can see, it's capturing the output of Html.Partial directly, and then performing the replacement on that. 如您所见,它直接捕获Html.Partial的输出,然后执行替换。 You'd use it in your view like so: 您可以在视图中使用它,如下所示:

@Html.PartialIE9TableFix("YourPartial")

However, to do this for actual views requires a lot more work, and certainly a lot more care when using it. 但是,要为实际视图执行此操作需要更多工作,并且在使用它时肯定会更加小心。 In order to do this, we actually need to capture, and modify, the response stream before it's sent to the client. 为了做到这一点,我们实际上需要在响应流发送到客户端之前捕获并修改它。

The IE9TableFixFilter below is very heavily based on code from Minify HTML with .NET MVC ActionFilter . 下面的IE9TableFixFilter非常基于Minify HTML with .NET MVC ActionFilter的代码。

using System;
using System.IO;
using System.Text;

public class IE9TableFixFilter : Stream
{
    public IE9TableFixFilter(Stream response, Func<string, string> filter)
    {
        this.response = response;
        this.filter = filter;
    }

    public override bool CanRead { get { return true; } }
    public override bool CanSeek { get { return true; } }
    public override bool CanWrite { get { return true; } }
    public override void Flush() { response.Flush(); }
    public override long Length { get { return 0; } }
    public override long Position { get; set; }

    public override int Read(byte[] buffer, int offset, int count)
    {
        return response.Read(buffer, offset, count);
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        return response.Seek(offset, origin);
    }

    public override void SetLength(long value)
    {
        response.SetLength(value);
    }

    public override void Close()
    {
        response.Close();
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        //byte[] data = new byte[count];
        //Buffer.BlockCopy(buffer, offset, data, 0, count);
        string s = Encoding.Default.GetString(buffer);

        s = filter(s);

        byte[] outData = Encoding.Default.GetBytes(s);
        response.Write(outData, 0, outData.GetLength(0));
    }

    private Stream response;
    private Func<string, string> filter;
}

The majority of code here is filling in implementations for abstract members of Stream . 这里的大部分代码都填充了Stream abstract成员的实现。 The important part is what's going on in the Write method. 重要的部分是Write方法中发生的事情。

The version of Write from the article first makes a copy of the bytes of the stream without actually using them. 本文中的Write版本首先制作流的字节副本,而不实际使用它们。 There's no mention there if this is for some specific reason, but it seems useless to me, so I commented those lines out. 如果这是出于某些特定原因,那里就没有提及,但它对我来说似乎毫无用处,所以我对这些内容进行了评论。

Next up, we need to create a simple ActionFilter to apply the response filter to: 接下来,我们需要创建一个简单的ActionFilter来将响应过滤器应用于:

using System.Text.RegularExpressions;
using System.Web.Mvc;

public class IE9TableFixFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var response = filterContext.HttpContext.Response;
        response.Filter = new IE9TableFixFilter(response.Filter,
            s => Regex.Replace(s, @"/td>\s+<td", "/td><td", RegexOptions.IgnoreCase));
    }
}

Now that's all done, I would strongly recommend that you don't apply this filter globally, instead choosing to decorate it on actions that require its use. 现在这一切都已完成,我强烈建议您不要全局应用此过滤器,而是选择在需要使用它的操作上进行装饰。 The reason for that is because it will naturally incur some performance penalty, so it's best to be explicit about when it's actually needed. 之所以这样,是因为它自然会产生一些性能损失,所以最好明确一下它何时需要它。 You won't need the partial extension method when using this. 使用它时,您不需要部分扩展方法。 So simply decorate your actions to use it: 所以只需装饰你的动作就可以使用它:

[IE9TableFixFilterAttribute]
public ActionResult Index()
{
    return View();
}

Update 更新

To make the filter attribute more efficient, you could actually just apply it to browsers that contain the user-agent string MSIE 9.0 : 要使过滤器属性更有效,您实际上只需将其应用于包含用户代理字符串MSIE 9.0浏览器:

public class IE9TableFixFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var request = filterContext.HttpContext.Request;
        var response = filterContext.HttpContext.Response;

        if (request.UserAgent.Contains("MSIE 9.0"))
        {
            response.Filter = new IE9TableFixFilter(response.Filter,
                s => Regex.Replace(s, @"/td>\s+<td", "/td><td", RegexOptions.IgnoreCase));
        }
    }
}

Other than clearing white-spaces, you may try one of the following fixes: 除了清除空格之外,您可以尝试以下修复之一:

  • CSS: td { white-space: nowrap; } CSS: td { white-space: nowrap; } td { white-space: nowrap; } if applicable! td { white-space: nowrap; }如果适用!

  • Force your tables to have fixed layout: 强制您的表格具有固定的布局:

 <table style="table-layout: fixed" width="600"> <colgroup> <col width="100"><col width="300"><col width="200"> </colgroup> <tr height="20"> <td>...</td> <td>...</td> <td>...</td> </tr> </table> 
  • If your web application already supports IE8, you can force IE9 users to use IE8 rendering engine by using: <meta http-equiv="X-UA-Compatible" content="IE=8" /> 如果您的Web应用程序已经支持IE8,您可以强制IE9用户使用IE8渲染引擎: <meta http-equiv="X-UA-Compatible" content="IE=8" />

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM