• ASP.NET 开发 WAP 网站


    随着手机上网的兴起,我们实际项目中可能会碰到专门针对手机开发的网站,虽然asp.net 也有专门的wap控件库,但在某些时候,这也不是完美的解决方案。asp.net webfrom具有高效开发网站的优势,但对于手机上网来说,viewstate确实是个大麻烦。本文根据自己的一些开发经验而来,也算是对项目的一个总结吧。

      虽然是基于asp.net webforms,但我并没有使用webfrom的任何控件,开发方式有点像asp或者jsp,但这也是为了避免产生任何viewstate而作的一个折中。就目前来说,wap网站的界面都还相对简单,大多以超链接为主,当然也可少许按钮,但以此方法都可以处理简单的逻辑。

      为了不产生viewstate,我们去掉了aspx页面中的<form runat="server"></form>标签,但在输出内容的格式,排版等,就要自己手动控制了。

      如下代码所示:

    ASP.NET WebForm开发WAP网站 - adyhpq - adyhpq的个人主页代码
    <table cellpadding="3" cellspacing="0">
    <%
    list
    <student> slist = student.createpersons();
    if (slist != null && slist.count > 0)
    {
    stringbuilder sb
    = new stringbuilder();
    foreach (student item in slist)
    {
    sb.append(
    "<tr><td><a href=\"../detail.aspx?id=");
    sb.append(item.studentid);
    sb.append(
    "\">");
    sb.append(item.studentid);
    sb.append(
    "</a></td><td>");
    sb.append(item.name);
    sb.append(
    "</td><td>");
    sb.append(item.major);
    sb.append(
    "</td></tr>");
    }

    response.write(sb.tostring());
    }
    %>
    </table>

    运行后,查看页面的html源代码,我们就会看到清洁的页面内容,如下图所示:

       ASP.NET WebForm开发WAP网站 - adyhpq - adyhpq的个人主页

      有爱好研究的同学,请下载demo查看具体。如有不足之处,还请指正。

      demo下载地址

    使用ASP.NET开发WAP很简单,只需要新建一个空的网站,向其中添加移动WEB窗体即可.可以使用OPERA浏览器与M3GATE来调试网页,

    强制输出WML,可以在WEB.CONFIG中 <system.web>下添加以下内容:

    <browserCaps>
                
    <result type="System.Web.Mobile.MobileCapabilities, System.Web.Mobile, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
                
    <use var="HTTP_USER_AGENT"/>
                        preferredRenderingType = "wml11"
                        preferredRenderingMime = "text/vnd.wap.wml"
                        preferredImageMime = "image/vnd.wap.wbmp"
    </browserCaps> 

    如果需要其它相关属性可以完整的添加设置属性:

    <browserCaps>
                
    <result type="System.Web.Mobile.MobileCapabilities, System.Web.Mobile, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
                
    <use var="HTTP_USER_AGENT"/>
                browser=Unknown
                version=0.0
                majorversion=0
                minorversion=0
                frames=false
                tables=false
                cookies=false
                backgroundsounds=false
                vbscript=false
                javascript=false
                javaapplets=false
                activexcontrols=false
                win16=false
                win32=false
                beta=false
                ak=false
                sk=false
                aol=false
                crawler=false
                cdf=false
                gold=false
                authenticodeupdate=false
                tagwriter=System.Web.UI.Html32TextWriter
                ecmascriptversion=0.0
                msdomversion=0.0
                w3cdomversion=0.0
                platform=Unknown
                css1=false
                css2=false
                xml=false
                mobileDeviceManufacturer = "Unknown"
                mobileDeviceModel = "Unknown"
                gatewayVersion = "None"
                gatewayMajorVersion = "0"
                gatewayMinorVersion = "0"
                preferredRenderingType = "wml11"
                preferredRenderingMime = "text/vnd.wap.wml"
                preferredImageMime = "image/vnd.wap.wbmp"
                defaultScreenCharactersWidth = "12"
                defaultScreenCharactersHeight = "6"
                defaultScreenPixelsWidth = "96"
                defaultScreenPixelsHeight = "72"
                defaultCharacterWidth = "8"
                defaultCharacterHeight = "12"
                screenBitDepth = "1"
                isColor = "false"
                inputType = "telephoneKeypad"
                numberOfSoftkeys = "0"
                maximumSoftkeyLabelLength = "5"
                canInitiateVoiceCall = "false"
                canSendMail = "true"
                hasBackButton = "true"
                rendersWmlDoAcceptsInline = "true"
                rendersWmlSelectsAsMenuCards = "true"
                rendersBreaksAfterWmlAnchor = "false"
                rendersBreaksAfterWmlInput = "false"
                rendersBreakBeforeWmlSelectAndInput = "true"
                requiresAttributeColonSubstitution = "true"
                requiresPhoneNumbersAsPlainText = "false"
                requiresUrlEncodedPostfieldValues = "false"
                requiredMetaTagNameValue = ""
                rendersBreaksAfterHtmlLists = "true"
                requiresUniqueHtmlCheckboxNames = "true"
                requiresUniqueHtmlInputNames = "true"
                requiresUniqueFilePathSuffix = "true"
                supportsCss = "false"
                hidesRightAlignedMultiselectScrollbars = "false"
                canRenderAfterInputOrSelectElement = "true"
                canRenderInputAndSelectElementsTogether = "true"
                canRenderOneventAndPrevElementsTogether = "true"
                canCombineFormsInDeck = "true"
                canRenderMixedSelects = "true"
                canRenderPostBackCards = "true"
                canRenderSetvarZeroWithMultiSelectionList = "true"
                supportsImageSubmit = "true"
                supportsSelectMultiple = "true"
                requiresHtmlAdaptiveErrorReporting = "false"
                requiresContentTypeMetaTag = "false"
                requiresDBCSCharacter = "false"
                requiresOutputOptimization = "false"
                supportsAccesskeyAttribute = "false"
                supportsInputIStyle = "false"
                supportsInputMode = "false"
                supportsIModeSymbols = "false"
                supportsJPhoneSymbols = "false"
                supportsJPhoneMultiMediaAttributes = "false"
                maximumRenderedPageSize = "2000"
                requiresSpecialViewStateEncoding = "false"
                requiresNoBreakInFormatting = "false"
                requiresLeadingPageBreak = "false"
                supportsQueryStringInFormAction = "true"
                supportsCacheControlMetaTag = "true"
                supportsUncheck = "true"
                canRenderEmptySelects = "true"
                supportsRedirectWithCookie = "true"
                supportsEmptyStringInCookieValue = "true"
                cachesAllResponsesWithExpires = "false"
                requiresNoSoftkeyLabels = "false"
                defaultSubmitButtonLimit = "1"
                supportsBold = "false"
                supportsItalic = "false"
                supportsFontSize = "false"
                supportsFontName = "false"
                supportsFontColor = "true"
                supportsBodyColor = "true"
                supportsDivAlign = "true"
                supportsDivNoWrap = "false"
                supportsCharacterEntityEncoding = "true"
                isMobileDevice="false"
            
    </browserCaps>

    乱码问题,可以在WEB.CONFIG中设置:

    <globalization   requestEncoding="UTF-8"       responseEncoding="UTF-8" />

    在OPERA或M3GATE中设置编码为UTF-3即可显示中文.

    使用MS自带的移动控件可以很方便的建立网站,如LINK,COMMAND,LABEL等

    使用ASP.NET开发移动通讯的几种方法 
    http://www.yesky.com/35/1640535.shtml 

    用VS2005实现ASP.NET2.0移动开发 
    http://dev.yesky.com/msdn/293/2371793.shtml 

    ASP.NET 2.0移动开发入门之基础 
    http://dev.yesky.com/msdn/373/2411873.shtml 

    ASP.NET 2.0移动开发入门之使用模拟器 
    http://dev.yesky.com/msdn/465/2471465.shtml 

    ASP.NET 2.0移动开发入门之使用样式 
    http://dev.yesky.com/msdn/230/2486230.shtml 

    ASP.NET 2.0移动开发之属性重写和模板化 
    http://dev.yesky.com/msdn/90/2570590.shtml 

    ASP.NET 2.0移动开发之定义设备筛选器 
    http://dev.yesky.com/msdn/117/2579117.shtml
    参考资料:http://dev.yesky.com

    俺用的工具有点落后,vs2008 express版。没用过asp.net mobile 开发过wap网站,

      于是想尽各种办法用asp.net 给实现了:

      刚出了点状况,代码下载下载源代码

    用asp.net开发移动wap网站集成在线wap模拟器

      注:通过目录下的/moni可以模拟浏览我们制作好的wap网站

      我们先实现一个Page类,添加一些于aspx页的交互,因为wap可能不支持viewState吧

      Page.cs 注意与System.Web.UI.Page分开哦

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    namespace Rsion.Web
    {
        public abstract class Page : System.Web.UI.Page
        {
            private TempDatas<string, Object> tempData;
            public Page() { BindEvents(); }
            /// <summary>
            /// 页面临时数据
            /// </summary>
            public TempDatas<String, Object> TempData
            {
                get
                {
                    if (tempData == null) tempData = new TempDatas<string, Object>();
                    return tempData;
                }
            }
            public PageAdapter Html
            {
                get { return new PageAdapter(this); }
            }
            /// <summary>
            /// 绑定事件
            /// </summary>
            protected virtual void BindEvents()
            {
            }
        }
    }

     Code


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Web;
    using Rsion.Web;
    namespace Rsion.Web
    {
        public abstract class Application:System.Web.HttpApplication
        {
            public static Template Template;
            /// <summary>
            /// 模板缓存时间
            /// </summary>
            public static int TemplateCacheTime = 10;
            /// <summary>
            /// 重启Web进程
            /// </summary>
            public static void RestartWebProcess()
            {
                HttpRuntime.UnloadAppDomain();
            }
        }
    }

      创建TempData用于与.aspx页数据交换


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Collections;
    // Author : Sonven
    // Blog   : Sonven.cnblogs.com
    namespace Rsion.Web
    {
        public class TempDatas<TKey,TValue>:CollectionBase
        {
            private Dictionary<TKey, TValue> dataArray;
            public TValue this[TKey key]
            {
                get
                {
                    if (dataArray.ContainsKey(key))return dataArray[key];
                    throw new ArgumentException("未添加此数据项进入该集合!", "TKey", null);
                }
                set
                {
                    dataArray = dataArray ?? new Dictionary<TKey, TValue>();
                    if (dataArray.ContainsKey(key)) dataArray[key] = value;
                    else dataArray.Add(key, value);
                }
            }
            /// <summary>
            /// 添加一个键值数据
            /// </summary>
            /// <param name="key"></param>
            /// <param name="value"></param>
            public void Add(TKey key, TValue value)
            {
                dataArray=dataArray??new Dictionary<TKey,TValue>();
                dataArray.Add(key,value);
            }
        }
    }

    我们扩展Page类创建一个PageAdapter.cs  (用于添加模板支持)


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Web.UI;
    using System.Web;
    using System.IO;
    using System.Text.RegularExpressions;
    namespace Rsion.Web
    {
        /// <summary>
        /// WebPage页面辅助适配器类
        /// </summary>
       public class PageAdapter
        {
           private Page page;
           public PageAdapter(Page page)
           {
               this.page = page;
           }
           /// <summary>
           /// 显示模板
           /// </summary>
           /// <param name="partialPath">模板文件路径:不带后缀[模板后缀.tpl]如/bottom将显示Templates下的bottom.tpl文件</param>
           public void RenderPartial(string partialPath)
           {
               string templateID="Template_"+partialPath.Replace("/", "_");
               object o =  HttpRuntime.Cache[templateID];
               if (o == null)
               {
                   FileInfo fi = new FileInfo(HttpContext.Current.Server.MapPath("~/templates/" + partialPath + ".tpl"));
                   if (!fi.Exists) return;
                   string templateContent;
                   using (StreamReader sr = new StreamReader(fi.FullName))
                   {
                       templateContent = sr.ReadToEnd();
                   }
                   //转换
                   TransformTemplateTags(ref templateContent);
                   //写入缓冲
                   HttpRuntime.Cache.Insert(templateID, templateContent, null,
                       DateTime.Now.AddMinutes(Application.TemplateCacheTime),TimeSpan.Zero);
                   HttpContext.Current.Response.Write(templateContent);
               }
               else
                   HttpContext.Current.Response.Write(o.ToString());
           }
           /// <summary>
           /// 转换模板内容
           /// </summary>
           /// <param name="templateContent"></param>
           private void TransformTemplateTags(ref string templateContent)
           {
               string templateID;
               string pattern=@"\${(\w+)}";
               Regex rg = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
               foreach(Match m in  rg.Matches(templateContent))
               {
                   templateID = Regex.Replace(m.Captures[0].Value, pattern, "$1");
                   templateContent = Regex.Replace(templateContent, @"\${" + templateID + "}",
                       Application.Template.Rules[templateID].ToString());
               }
           }
           /// <summary>
           /// 转换该页的标签内容
           /// </summary>
           public void TransformPageTags()
           {
               ///
               ///TO:DO..
               ///
           }
        }
    }

     现在我们要实现可以用于wap的page类了,WapPage.cs


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Web;
    using System.Web.UI;
    using System.IO;
    // Author : Sonven
    // Blog   : Sonven.cnblogs.com
    namespace Rsion.Web
    {
        public class WapPage:Page
        {
            public WapPage() : base() { }
            /// <summary>
            /// 绑定事件
            /// </summary>
            protected override void BindEvents()
            {
                Page.Load += delegate(object s, EventArgs e)
                {
                    HttpContext.Current.Response.Write("<?xml version=\"1.0\"?>\r" +
                        "<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\" \"http://www.wapforum.org/DTD/wml_1.1.xml\">\r");
                };
                Page.LoadComplete += delegate(object s, EventArgs e)
                {
                    HttpContext.Current.Response.ContentType = "text/vnd.Web.wml";
                };
                //处理错误时候转向错误页面[仅在发布后]
                #if DEBUG
                #else
                Page.Error += delegate(object s, EventArgs e)
                {
                    Session["errormsg"] = HttpContext.Current.Error.Message + "<br />" +
                        "地址:" + HttpContext.Current.Request.RawUrl.ToString();
                    HttpContext.Current.Response.Redirect("~/error.aspx");
                };
                #endif
                Page.PreRender += delegate(object s, EventArgs e)
                {
                };
            }
        }
    }

     这样就差不多只要继承WapPage就可以实现wap网页开发了

      接下来我们创建模板,并给模板加上缓存提高性能

      Application.cs用于提供缓存时间

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Web;
    using Rsion.Web;
    namespace Rsion.Web
    {
        public abstract class Application:System.Web.HttpApplication
        {
            public static Template Template;
            /// <summary>
            /// 模板缓存时间
            /// </summary>
            public static int TemplateCacheTime = 10;
            /// <summary>
            /// 重启Web进程
            /// </summary>
            public static void RestartWebProcess()
            {
                HttpRuntime.UnloadAppDomain();
            }
        }
    }

      接下来我们创建一个单独的Template项目先

      在里面创建Template.cs,ParamRules

      ParamRules实现如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Collections;
    namespace Rsion.Web
    {
        /// <summary>
        /// 模板参数规则类
        /// </summary>
        public class ParamRules:IEnumerable
        {
            private Dictionary<string, object> rules;
            public ParamRules()
            {
                if (rules == null) rules = new Dictionary<string, object>();
            }
            public object this[string paramKey]
            {
                get
                {
                    if (rules.ContainsKey(paramKey)) return rules[paramKey];
                    return "";
                }
                set
                {
                    if (rules.ContainsKey(paramKey)) rules[paramKey] = value;
                    else rules.Add(paramKey, value);
                }
            }
            /// <summary>
            /// 添加新的规则
            /// </summary>
            /// <param name="paramKey"></param>
            /// <param name="paramValue"></param>
            public void Add(string paramKey, object paramValue)
            {
                if (rules.ContainsKey(paramKey))
                    throw new ArgumentException("对不起规则已经存在!Key:" + paramKey + ",Value:" + rules[paramKey].ToString(), "paramKey");
                rules.Add(paramKey, paramValue);
            }
            public void Remove(string paramKey, object paramValue)
            {
                if (rules.ContainsKey(paramKey))
                    rules.Remove(paramKey);
            }
            #region IEnumerable 成员
            public IEnumerator GetEnumerator()
            {
                foreach (KeyValuePair<string, object> k in rules)
                {
                    yield return k;
                }
            }
            #endregion
        }
    }

    Template.cs实现如下:


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    namespace Rsion.Web
    {
        /// <summary>
        /// 模板
        /// </summary>
        public class Template
        {
            public static Template _template;
            private static ParamRules rules;
            private Template() { }
            public static Template CreateInstance()
            {
                if (_template == null) _template = new Template();
                return _template;
            }
            public ParamRules Rules
            {
                get
                {
                    if (rules == null) rules = new ParamRules();
                    return rules;
                }
            }
            
        }
    }

      这样我们先在global.asax中填加一些模板数据,这样才可以解析模板,解析模板的功能实现在PageAdapter中,这样可以

      在本页面直接调用Html.RenderPartial("template")调用

      gobal.asax


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Security;
    using System.Web.SessionState;
    using Rsion.Web;
    using c=Rsion.Web.Config;
    namespace Rsion.Wap
    {
        public class Global : System.Web.HttpApplication
        {
            protected void Application_Start(object sender, EventArgs e)
            {
                InitTemplate();//初始化模板数据,只针对那些不经常变化的数据
            }
            # region events
            protected void Session_Start(object sender, EventArgs e)
            {
            }
            protected void Application_BeginRequest(object sender, EventArgs e)
            {
            }
            protected void Application_AuthenticateRequest(object sender, EventArgs e)
            {
            }
            protected void Application_Error(object sender, EventArgs e)
            {
            }
            protected void Session_End(object sender, EventArgs e)
            {
            }
            protected void Application_End(object sender, EventArgs e)
            {
            }
            #endregion
            private void InitTemplate()
            {
                global::Rsion.Web.Template t = Template.CreateInstance();
                //添加模板数据规则,只用于不常更新的数据  如key=webname 则{$webname}替换成value
                t.Rules.Add("webname",c.Web.Current.WebName);
                t.Rules.Add("weburi", c.Web.Current.WebUri);
                t.Rules.Add("sysname", "sonven's wap develop framework!");
                Rsion.Web.Application.Template = t;
                //模板缓存过期时间(分钟)(默认10分钟)
                Rsion.Web.Application.TemplateCacheTime = 0;
            }
        }
    }

     然后着手开发wap项目了

      首先新建一个default.aspx,default.aspx.cs

      两文件如下


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using Rsion.Web.Config;
    using Rsion.Web;
    namespace Rsion.Wap
    {
        public partial class Default:WapPage
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                if (!Page.IsPostBack)
                {
                    TempData.Add("webname", Gobal.Web.WebName);
                    TempData.Add("webUri", Gobal.Web.WebUri);
                }
            }
        }
    }

      default.aspx


    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Rsion.Wap.Default" %>
    <wml>
    <head></head>
    <card title="<%=TempData["webname"] %>">
        <%Html.RenderPartial("top"); %>
        <%Html.RenderPartial("index"); %>
        数据绑定用&lt;%=TempData[id] %&gt;<br /><br />调用显示模板&lt;% Html.RenderPartial(&quot;<br />模板在Templates下的路径不包括.tpl)<br />
        模板中用:${templateId}代替符号<br />
        然后在使用Rsion.Web.Application.<br />Template.Rules.Add(templateID,value)<br />
        就可以调出value值了!
        
        <%Html.RenderPartial("bottom"); %>
    </card>
    </wml>

     怎么样呢是不是很简单,接着创建模板

      文件放在/Templates/下哦,文件扩展为.tpl

      bottom.tpl


    <br />
    <a href="/">首页</a> | 
    <a href="http://www.cnyolee.com">有理网</a> |
    <a href="http://sonven.cnblogs.com">博客园</a> |
    <a href="http://www.rsion.com">联系我</a>
    <br />
     ${webname} ${weburi}

      同理创建其他的模板

      我们在Page类里面实现了友好的自定义错误页,我们创建显示这个页面的error.aspx

      error.aspx

      Code


    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Error.aspx.cs" Inherits="Rsion.Wap.Error" %>
    <wml>
    <card title="对不起出错了!">
        手机锐讯网 Web.rsion.com <br />
        错误信息:<br />
        <%=TempData["errormsg"]%>
    </card>
    </wml>

      Code


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using Rsion.Web;
    namespace Rsion.Wap
    {
        public partial class Error:WapPage
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                if (!Page.IsPostBack)
                {
                   this.TempData["errormsg"] = Session["errormsg"] ?? "系统执行出错!";
                }
            }
        }
    }

     

      Ok了接下来就该验收结果了,达开/moni在里面输入你的地址就可以看到wap已经可以正常在浏览器中显示了

    本文示例源代码或素材下载

  • 相关阅读:
    Create, Read, Write, Copy, Move and Delete a Text File using C#
    财富人生访谈
    aspnetdb数据库简介
    asp.net基于Profile和Provider技术实现购物车
    IIS7的FTP设置
    DataRow[]用作DataSource找不到列的问题
    SMTP 550错误
    简单的文件上传代码
    选取哪个字段作为分区依据
    IIS7的虚拟目录设置独立应用程序池
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/1931840.html
Copyright © 2020-2023  润新知