zoukankan      html  css  js  c++  java
  • 继续不走寻常路:ASP.NET MVC中使用Web Forms用户控件

    目前我们正在用ASP.NET MVC(Razor)开发新版博客后台,在开发中遇到一个棘手的问题:如何在ASP.NET MVC中使用第三方开发的Web Forms用户控件,比如CuteEditor。

    如果是商业软件,你无法用ASP.NET MVC进行重写;即使是开源软件,你也不可能花时间去重写。你只要两个选择:要么搞定这个问题?要么放弃使用ASP.NET MVC?

    搞软件开发,一个吸引人的地方就是“一切皆有可能”,对于面临的技术问题,只要下定决心去解决,通常都能找到解决方法。

    对于这个问题,我们的思路是:Web Forms用户控件最终输出的就是一段包含HTML代码的字符串,只要拿到这个字符串,通过控制器将字符串传给视图,就能解决问题。

    有了这个思路,我们首先要解决的就是在控制器中得到用户控件的输出字符串,这不是难题,可以用三架马车(StringBuilder+StringWriter+HtmlTextWriter)搞定,代码如下:

    string controlOutput = string.Empty;
    BlogEditor editor
    = new CuteEditorForCNBlogs();
    StringBuilder sb
    = new StringBuilder();
    using (StringWriter sw = new StringWriter(sb))
    {
    using (HtmlTextWriter htw = new HtmlTextWriter(sw))
    {
    editor.RenderControl(htw);
    controlOutput
    = sb.ToString();
    }
    }

    然后,通过ViewBag传递给视图,代码如下:

    ViewBag.EditorHtml = controlOutput;

    最后,在视图中显示一下就搞定(只搞定了部分Web Forms控件),代码如下:

    @{
    Layout = "~/Views/Admin/_AdminLayout.cshtml";
    }
    <div id="editor">
    <div id="editor_main">
    <div>标题</div>
    <input type="text" id="txtTitle" value="" />
    <div>内容</div>
    @Html.Raw(ViewBag.EditorHtml)
    <div><input type="button" value="发布"/></div>
    </div>
    </div>

    到这步,原以为大功告成...在测试CuteEditor控件时,发现革命尚需努力,CuteEditor未能正常输出。

    通过错误信息发现CuteEditor调用了this.Page.Request,而实际Page的值为null。

    于是,我们创建了一个Page的实例,通过Controls.Add将CuteEditor加载到Page实例中,代码如下:

    Page page = new Page();
    string controlOutput = string.Empty;
    BlogEditor editor
    = new CuteEditorForCNBlogs();
    page.Controls.Add(editor);
    ...

    增加Page实例之后,发现Page.Request为null,而且Page.Request为只读属性,无法在创建Page的实例之后进行赋值。

    找遍Page的方法与属性,都没有找到为Page.Request赋值的办法。

    剩下的唯一的希望就是借助Reflector深入“虎穴”,功夫不负有心人,终于发现“虎子”—— SetIntrinsics(HttpContext context):

    private void SetIntrinsics(HttpContext context)
    {
    this.SetIntrinsics(context, false);
    }
    private void SetIntrinsics(HttpContext context, bool allowAsync)
    {
    this._request = context.Request;
    }

    可是,SetIntrinsics是私有方法, 仅供内部使用,咋办?用“反射”挖地道呗。挖地道秘方如下:

    Page page = new Page();
    page.GetType().InvokeMember(
    "SetIntrinsics", BindingFlags.NonPublic |
    BindingFlags.Instance
    | BindingFlags.InvokeMethod, null, page,
    new object[] { System.Web.HttpContext.Current });

    地道挖好,就大功告成,ASP.NET MVC控制器中的完整代码:

    public ActionResult NewPost()
    {
    Page page
    = new Page();
    page.GetType().InvokeMember(
    "SetIntrinsics", BindingFlags.NonPublic |
    BindingFlags.Instance
    | BindingFlags.InvokeMethod, null, page,
    new object[] { System.Web.HttpContext.Current });
    string controlOutput = string.Empty;
    BlogEditor editor
    = new CuteEditorForCNBlogs();
    page.Controls.Add(editor);
    StringBuilder sb
    = new StringBuilder();
    using (StringWriter sw = new StringWriter(sb))
    {
    using (HtmlTextWriter htw = new HtmlTextWriter(sw))
    {
    editor.RenderControl(htw);
    controlOutput
    = sb.ToString();
    }
    }
    ViewBag.EditorHtml
    = controlOutput;
    return View("EditPost");
    }

    继续ASP.NET MVC之旅...

    更新:

    根据Ivony...的建议,使用Server.Execute更简单,代码如下:

    public ActionResult NewPost()
    {
    Page page
    = new Page();
    string controlOutput = string.Empty;
    BlogEditor editor
    = new CuteEditorForCNBlogs();
    page.Controls.Add(editor);
    StringBuilder sb
    = new StringBuilder();
    using (StringWriter sw = new StringWriter(sb))
    {
    using (HtmlTextWriter htw = new HtmlTextWriter(sw))
    {
    Server.Execute(page, htw,
    false);
    controlOutput
    = sb.ToString();
    }
    }
    ViewBag.EditorHtml
    = controlOutput;
    return View("EditPost");
    }

  • 相关阅读:
    Android学习笔记(四十):Preference的使用
    怎样在小方框上打对号 小方框内打对勾 word 方框打对勾
    PreTranslateMessage作用和用法
    MyBatis与Spring设置callSettersOnNulls
    EJB3.0开发环境的搭建
    经常使用虚拟现实仿真软件总汇(zz)
    slf自己主动绑定实现类过程推断
    DLNA介绍(包含UPnP,2011/6/20 更新)
    从技术到管理的问题
    NOI第一天感想&小结
  • 原文地址:https://www.cnblogs.com/dudu/p/asp_net_mvc_user_control.html
Copyright © 2011-2022 走看看