一个用于手动生成Podcast的RSS种子的小Web应用。用到了如下几个技术:
基本数据库结构为:
其中UserId等于aspnet_Users表中的UserId,而Items通过UserId和ChannelName共同外键关联Channels。
默认情况下,通过VS的ASP.NET Configuration功能来对网站添加Membership等功能,会自动添加一个ASPNET的数据库文件,那么如何使用现存的数据库呢?
另外,再按照如下设置即可:
<membership defaultProvider="SqlProvider" userIsOnlineTimeWindow="15">
<providers>
<clear />
<add name="SqlProvider"
type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
connectionStringName="PodcastPublisherConnectionString" applicationName="PodcastPublisher" enablePasswordRetrieval="false"
enablePasswordReset="true" requiresQuestionAndAnswer="true" requiresUniqueEmail="true" passwordFormat="Hashed"
minRequiredPasswordLength="4" minRequiredNonalphanumericCharacters="0" />
</providers>
</membership>
其中,把applicationName的默认值“/”改为“PodcastPublisher”是作为以后托管于虚拟目录上,而非根站点。
和ASP.NET 2.0 Membership Service结合,可以免去自己写登录,注销的代码,还能自动完成注册新用户,改变密码,重置密码的功能。大家可以从代码中看到,我在Default.aspx、Login.aspx、Register.aspx和ChangePassword.aspx中根本没有写一句后置代码。
其实在IIS7中,登录控件还能用于PHP的Web应用程序。
ASP.NET 2.0提供了一种新特性Data Source Control,包括ObjectDataSource、SqlDataSource、AccessDataSource和XmlDataSource,在ASP.NET 3.5中,额外包括了LinqDataSource。
在此示例程序中,我一开始本来想用LinqDataSource的,也确实基本都写好了,可惜调试运行的时候总是添加数据有问题(后面说问题出在那里)。后来不得不改用SqlDataSource。
通过把SqlDataSource和GridView、DetailsView想结合,可以很容易地开发出操作数据的页面。如Channels.aspx和Items.aspx。
在这里有一个技巧,如何根据登录用户筛选数据,添加数据时如何添加当前用户的ID呢?
首先编写一个方法来获取UserId,并在Session中添加这个值
protected void Page_Load(object sender, EventArgs e)
{
if (this.Session["UserId"] == null)
{
this.Session.Add("UserId", GetUserId());
}
}
private Guid GetUserId()
{
MembershipUser user = Membership.GetUser();
return (Guid)user.ProviderUserKey;
}
然后,在SqlDataSource中,设置SelectCommand="SELECT [Name], [Title], [Link], [Description], [Language], [Copyright], [LastBuildDate] FROM [Channels] WHERE ([UserId] = @UserId)" ,以及设置
<SelectParameters>
<asp:SessionParameter Name="UserId" SessionField="UserId"/>
</SelectParameters>
InsertParameters操作也是同理。在LinqDataSource中,这个参数老是出错,就算我根据网络上的资料,把Type改为“Empty”还是不行(可以Select,但是Insert就有问题)。
以上这些参数可以通过设计器来添加,即使使用SqlDataSource的SmartTag来操作,不过要记得把参数的Type删除掉,不然不识别Guid的类型。
另外一个小技巧,如何把GridView、DetailsView显示的数据同步呢?只需这样:
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
DetailsView1.PageIndex = GridView1.SelectedIndex;
}
我这里就很简单地使用UpdatePanel,以及UpdateProgress。具体的看Channels.aspx和Items.aspx页面。
一开始使用SqlDataSource的时候,没有意识要获取其中数据这样麻烦,所以干脆直接使用LINQ to SQL获取数据。见Items.aspx.cs中的Button1_Click
我使用LINQ to XML来生成特定格式的xml,并保存在数据库的某个字段中。这里有个小技巧,就是生成xml数据的嵌套:
XDocument xdoc = new XDocument(
new XElement("rss", new XAttribute("version", "2.0"),
new XElement("channel",
new XElement("title", channel.Title),
new XElement("link", channel.Link ?? ""),
new XElement("description", channel.Description ?? ""),
new XElement("language", channel.Language ?? ""),
new XElement("copyright", channel.Copyright ?? ""),
new XElement("lastBuildDate", DateTime.Now),
new XElement("generator", "Podcast Publisher"),
new XElement("webMaster", Session["UserId"].ToString()),
new XElement("ttl", 1),
GetChildItems(channel.Items)
)
)
);
在这篇文章中,我详细介绍过LINQ to SQL的批量删除的方法。不过我用的是批量删除之投机取巧版,我的调用代码如下:
DataClassesDataContext dc = new DataClassesDataContext();
var query = from item in dc.Items
where item.UserId == userId && item.ChannelName == chName && item.PubDate.AddDays(10)<= DateTime.Now
select item;
dc.DeleteAll(query);
通过IIS7的管理器进行配置,保存在web.config中:
<rewrite>
<rules>
<rule name="RSS">
<match url="([_0-9a-z-]+)/([_0-9a-z-]+)/rss" />
<action type="Rewrite" url="rss.aspx?user={R:1}&channel={R:2}" />
</rule>
</rules>
</rewrite>
这是把对rss.aspx的访问转发为username/channelname/rss的地址
关于IIS7的使用可以看这里:http://learn.iis.net/page.aspx/460/using-url-rewrite-module/
========================
整个示例程序的源代码下载地址:http://www.91files.com/?YN9F9KU1PNB71UQR9FWD