ASP.net“BasePage”类的想法

时间:2010-01-14 14:57:29

标签: c# asp.net

将哪些很酷的功能和方法添加到您的ASP.net BasePage : System.Web.UI.Page课程中?

实施例

这是我用于身份验证的内容,我想听听您对此的意见:

protected override void OnPreInit(EventArgs e)
{
    base.OnPreInit(e);

    // Authentication code omitted... Essentially same as below.

    if (_RequiresAuthentication && !(IsAuthorized))
    {
        RespondForbidden("You do not have permissions to view this page.", UnauthorizedRedirect);
        return;
    }
}

// This function is overridden in each page subclass and fitted to each page's
// own authorization requirements.
// This also allows cascading authorization checks,
// e.g: User has permission to view page? No - base.IsAuthorized - Is user an admin?
protected virtual bool IsAuthorized
{
    get { return true; }
}

我的BasePage类包含此类的实例:

public class StatusCodeResponse {

    public StatusCodeResponse(HttpContext context) {
        this._context = context;
    }

    /// <summary>
    /// Responds with a specified status code, and if specified - transfers to a page.
    /// </summary>
    private void RespondStatusCode(HttpContext context, System.Net.HttpStatusCode status, string message, string transfer)
    {
        if (string.IsNullOrEmpty(transfer))
        {
            throw new HttpException((int)status, message);
        }

        context.Response.StatusCode = (int)status;
        context.Response.StatusDescription = message;
        context.Server.Transfer(transfer);
    }

    public void RespondForbidden(string message, string transfer)
    {
        RespondStatusCode(this._context, System.Net.HttpStatusCode.Forbidden, message, transfer);
    }

    // And a few more like these...

}

作为旁注,这可以使用HttpResponse对象的扩展方法来完成。

另一种方法我觉得解析querystring int参数非常方便:

public bool ParseId(string field, out int result)
{
    return (int.TryParse(Request.QueryString[field], out result) && result > 0);
}

9 个答案:

答案 0 :(得分:5)

  • 会话相关的东西,BasePage中映射到会话的一些复杂对象,并将其作为属性公开。
  • 做填充碎屑垫物的事情。

但最重要的是:不要让你的基页进入某个帮助类。不要添加像ParseId()这样的东西,这太荒谬了。


另外,根据第一篇文章:制作IsAuthorized 抽象之类的内容。这样,如果有人忘记了某种虚拟方法,就不会创建巨大的安全漏洞。

答案 1 :(得分:3)

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;

namespace MySite
{
    /// <summary>
    /// Base class with properties for meta tags for content pages
    /// http://www.codeproject.com/KB/aspnet/PageTags.aspx
    /// http://weblogs.asp.net/scottgu/archive/2005/08/02/421405.aspx
    /// </summary>
    public partial class BasePage : System.Web.UI.Page
    {
        private string keywords;
        private string description;


        /// <SUMMARY>
        /// Gets or sets the Meta Keywords tag for the page
        /// </SUMMARY>
        public string Meta_Keywords
        {
            get
            {
                return keywords;
            }
            set
            {
                // Strip out any excessive white-space, newlines and linefeeds
                keywords = Regex.Replace(value, "\\s+", " ");
            }
        }

        /// <SUMMARY>
        /// Gets or sets the Meta Description tag for the page
        /// </SUMMARY>
        public string Meta_Description
        {
            get
            {
                return description;
            }
            set
            {
                // Strip out any excessive white-space, newlines and linefeeds
                description = Regex.Replace(value, "\\s+", " ");
            }
        }


        // Constructor
        // Add an event handler to Init event for the control
        // so we can execute code when a server control (page)
        // that inherits from this base class is initialized.
        public BasePage()
        {
            Init += new EventHandler(BasePage_Init); 
        }


        // Whenever a page that uses this base class is initialized,
        // add meta keywords and descriptions if available
        void BasePage_Init(object sender, EventArgs e)
        {
            if (!String.IsNullOrEmpty(Meta_Keywords))
            {
                HtmlMeta tag = new HtmlMeta();
                tag.Name = "keywords";
                tag.Content = Meta_Keywords;
                Header.Controls.Add(tag);
            }

            if (!String.IsNullOrEmpty(Meta_Description))
            {
                HtmlMeta tag = new HtmlMeta();
                tag.Name = "description";
                tag.Content = Meta_Description;
                Header.Controls.Add(tag);
            }
        }
    }
}

答案 2 :(得分:3)

除了已经提到的元数据(主要是obsolete in ASP.NET 4.0以及新的Page.MetaDescriptionPage.MetaKeywords属性),我还有一些方法可以向我的页面添加其他标题链接,例如特定的用于添加页面特定的CSS,或者诸如cannonical链接,RSS链接等的东西:

/// <overloads>
/// Adds a CSS link to the page. Useful when you don't have access to the
///  HeadContent ContentPlaceHolder. This method has 4 overloads.
/// </overloads>
/// <summary>
/// Adds a CSS link.
/// </summary>
/// <param name="pathToCss">The path to CSS file.</param>
public void AddCss(string pathToCss) {
    AddCss(pathToCss, string.Empty);
}

/// <summary>
/// Adds a CSS link in a specific position.
/// </summary>
/// <param name="pathToCss">The path to CSS.</param>
/// <param name="position">The postion.</param>
public void AddCss(string pathToCss, int? position) {
    AddCss(pathToCss, string.Empty, position);
}

/// <summary>
/// Adds a CSS link to the page with a specific media type.
/// </summary>
/// <param name="pathToCss">The path to CSS file.</param>
/// <param name="media">The media type this stylesheet relates to.</param>
public void AddCss(string pathToCss, string media) {
    AddHeaderLink(pathToCss, "text/css", "Stylesheet", media, null);
}

/// <summary>
/// Adds a CSS link to the page with a specific media type in a specific
/// position.
/// </summary>
/// <param name="pathToCss">The path to CSS.</param>
/// <param name="media">The media.</param>
/// <param name="position">The postion.</param>
public void AddCss(string pathToCss, string media, int? position) {
    AddHeaderLink(pathToCss, "text/css", "Stylesheet", media, position);
}

/// <overloads>
/// Adds a general header link. Useful when you don't have access to the
/// HeadContent ContentPlaceHolder. This method has 3 overloads.
/// </overloads>
/// <summary>
/// Adds a general header link.
/// </summary>
/// <param name="href">The path to the resource.</param>
/// <param name="type">The type of the resource.</param>
public void AddHeaderLink(string href, string type) {
    AddHeaderLink(href, type, string.Empty, string.Empty, null);
}

/// <summary>
/// Adds a general header link.
/// </summary>
/// <param name="href">The path to the resource.</param>
/// <param name="type">The type of the resource.</param>
/// <param name="rel">The relation of the resource to the page.</param>
public void AddHeaderLink(string href, string type, string rel) {
    AddHeaderLink(href, type, rel, string.Empty, null);
}

/// <summary>
/// Adds a general header link.
/// </summary>
/// <param name="href">The path to the resource.</param>
/// <param name="type">The type of the resource.</param>
/// <param name="rel">The relation of the resource to the page.</param>
/// <param name="media">The media target of the link.</param>
public void AddHeaderLink(string href, string type, string rel, string media)
{
    AddHeaderLink(href, type, rel, media, null);
}

/// <summary>
/// Adds a general header link.
/// </summary>
/// <param name="href">The path to the resource.</param>
/// <param name="type">The type of the resource.</param>
/// <param name="rel">The relation of the resource to the page.</param>
/// <param name="media">The media target of the link.</param>
/// <param name="position">The postion in the control order - leave as null
/// to append to the end.</param>
public void AddHeaderLink(string href, string type, string rel, string media, 
                          int? position) {
  var link = new HtmlLink { Href = href };

  if (0 != type.Length) {
    link.Attributes.Add(HtmlTextWriterAttribute.Type.ToString().ToLower(), 
                        type);
  }

  if (0 != rel.Length) {
    link.Attributes.Add(HtmlTextWriterAttribute.Rel.ToString().ToLower(),
                        rel);
  }

  if (0 != media.Length) {
    link.Attributes.Add("media", media);
  }

  if (null == position || -1 == position) {
    Page.Header.Controls.Add(link);
  }
  else
  {
    Page.Header.Controls.AddAt((int)position, link);
  }
}

答案 3 :(得分:1)

通过覆盖InitializeCulture()方法进行文化初始化(从cookie或DB设置文化和ui文化)。

我的一些应用程序是可品牌化的,然后我在这里做了一些“品牌化”的东西。

答案 4 :(得分:1)

我用这个methot并感谢你的,

/// <summary>
        /// Displays the alert.
        /// </summary>
        /// <param name="message">The message to display.</param>
        protected virtual void DisplayAlert(string message)
        {
            ClientScript.RegisterStartupScript(
                            GetType(),
                            Guid.NewGuid().ToString(),
                            string.Format("alert('{0}');", message.Replace("'", @"\'")),
                            true
                        );
        }

        /// <summary>
        /// Finds the control recursive.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns>control</returns>
        protected virtual Control FindControlRecursive(string id)
        {
            return FindControlRecursive(id, this);
        }

        /// <summary>
        /// Finds the control recursive.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <param name="parent">The parent.</param>
        /// <returns>control</returns>
        protected virtual Control FindControlRecursive(string id, Control parent)
        {
            if (string.Compare(parent.ID, id, true) == 0)
                return parent;

            foreach (Control child in parent.Controls)
            {
                Control match = FindControlRecursive(id, child);

                if (match != null)
                    return match;
            }

            return null;
        }

答案 5 :(得分:1)

将授权代码放在基页中通常不是一个好主意。问题是,如果您忘记从基页派生需要授权的页面,会发生什么?你将有一个安全漏洞。

使用HttpModule要好得多,这样你就可以拦截所有页面的请求,并确保用户在HttpHandler有机会运行之前就被授权了。

此外,正如其他人所说,并且为了与OO原则保持一致,最好只在基页中使用与页面本身相关的方法。如果他们不引用“this”,他们可能应该在帮助类中 - 或者可能是扩展方法。

答案 6 :(得分:0)

当我需要某些属性和每个页面时,我从System.Web.UI.Page继承。这对于实现登录的aweb应用程序很有用。在成员资格页面中,我使用自己的基类来访问属性,如UserID,UserName等。这些属性包装会话变量

答案 7 :(得分:0)

以下是我使用自定义基类的一些示例(无代码):

  1. 添加页面过滤器(例如将“{theme}”替换为“〜/ App_Theme / [currentTheme]”),
  2. 根据站点地图添加属性并处理自动标题页面,
  3. 注册专门的日志记录(可能通过不同方式重做),
  4. 使用全局重定向器添加通用输入(Form / Querystring)验证方法:AddRequiredInput(“WidgetID”,PageInputType.QueryString,typeof(string)),
  5. 站点地图帮助程序,允许将静态“编辑类”更改为与“编辑秋季'10科学101”相关的上下文等内容
  6. ViewState Helpers,允许我将页面上的变量注册到名称,并让它自动从视图状态或默认值填充该变量,并在请求结束时将值保存回viewstate。
  7. 自定义404重定向器,我可以在其中传递异常或消息(或两者),它将转到我已预定义的页面,以便很好地显示和记录它。
  8. 我个人最喜欢#5因为a)更新SiteMap是丑陋的,我不喜欢弄乱页面,使其更具可读性; b)它使SiteMap更加用户友好。

答案 8 :(得分:0)

请参阅Getting page specific info in ASP.Net Base Page

public abstract string AppSettingsRolesName { get; }

List<string> authorizedRoles = new List<string>((ConfigurationManager.AppSettings[AppSettingsRolesName]).Split(','))
if (!authorizedRoles.Contains(userRole))
{
Response.Redirect("UnauthorizedPage.aspx");
}

在派生页面中

public override string AppSettingsRolesName 
{
  get { return "LogsScreenRoles"; }
}