I've been working with TheBeerHouse Starter Kit (TBH). I found it useful for learning n-tier architecture, however I have noticed the following issue and so far no answer has been found.
TBH povides an Articles section to post, browse articles, etc.. This page is displayed to show the available categories:
http://localhost:xxxx/TBH_Web/ShowCategories.aspx
Once you pick one of the categories, TBH will display another page, BrowseArticles.aspx, which displays the articles belonging to the category selected:
http://localhost:xxxx/TBH_Web/BrowseArticles.aspx?CatID=40
BrowseArticles.aspx uses a user control to display the available articles in the category. It also has a drop-down-list to allow you to select from a list of available categories to select another category for which to display articles.
When I change categories from the dropdownlist and select another category, the articles displayed in the grid of the user control change and correctly display for the newly selected category. I am assuming this is accomplished using a PostBack?
The issue is that TBH is not rewriting the query string when I change categories. The URL query string still stays as:
http://localhost:xxxx/TBH_Web/BrowseArticles.aspx?CatID=40
instead of changing the CatID parameter to the number corresponding to the ID of the newly selected category, something like:
http://localhost:xxxx/TBH_Web/BrowseArticles.aspx?CatID=28
The biggest problem this causes is that this becomes an issue for bookmarking - it is not possible to bookmark the page that you really want because the bookmark still points to the articles in the previous category.
I have looked through the code for Server.Transfer calls instead of Response.Redirect, but found none. I didn't find any Response.Redirect calls either however.
Please write any suggestions!!! I would like to continue using and learning TBH starter kit architecture, but this issue is a major drawback if bookmarking cannot be accomplished.
----------
I am including the UI Layer and Business Layer code below.
BrowseArticles.aspx
1 <%@ Page Language="C#" MasterPageFile="~/Template.master" AutoEventWireup="true" CodeFile="BrowseArticles.aspx.cs" Inherits="MB.TheBeerHouse.UI.BrowseArticles" Title="The Beer House - Articles" %>
2 <%@ MasterType VirtualPath="~/Template.master" %>
3 <%@ Register src="./Controls/ArticleListing.ascx" TagName="ArticleListing" TagPrefix="mb" %>
4
5 <asp:Content ID="MainContent" ContentPlaceHolderID="MainContent" Runat="Server">
6 <div class="sectiontitle">Article List</div>
7 <p></p>
8 <mb:ArticleListing id="ArticleListing1" runat="server" PublishedOnly="True" />
9 </asp:Content>
BrowseArticles.aspx.cs
1 using System;
2 using System.Data;
3 using System.Configuration;
4 using System.Collections;
5 using System.Web;
6 using System.Web.Security;
7 using System.Web.UI;
8 using System.Web.UI.WebControls;
9 using System.Web.UI.WebControls.WebParts;
10 using System.Web.UI.HtmlControls;
11 using MB.TheBeerHouse;
12
13 namespace MB.TheBeerHouse.UI
14 {
15 public partial class BrowseArticles : BasePage
16 {
17 protected void Page_Load(object sender, EventArgs e)
18 {
19 this.Master.EnablePersonalization = true;
20 }
21 }
22 }
\Controls\ArticleListing.ascx1 <%@ Control Language="C#" AutoEventWireup="true" CodeFile="ArticleListing.ascx.cs" Inherits="MB.TheBeerHouse.UI.Controls.ArticleListing" %>
2 <%@ Register src="../Controls/RatingDisplay.ascx" TagName="RatingDisplay" TagPrefix="mb" %>
3
4 <asp:Literal runat="server" ID="lblCategoryPicker"><small><b>Filter by category:</b></small></asp:Literal>
5 <asp:DropDownList ID="ddlCategories" runat="server" AutoPostBack="True" DataSourceID="objAllCategories"
6 DataTextField="Title" DataValueField="ID" AppendDataBoundItems="true" OnSelectedIndexChanged="ddlCategories_SelectedIndexChanged">
7 <asp:ListItem Value="0">All categories</asp:ListItem>
8 </asp:DropDownList>
9 <asp:ObjectDataSource ID="objAllCategories" runat="server" SelectMethod="GetCategories"
10 TypeName="MB.TheBeerHouse.BLL.Articles.Category"></asp:ObjectDataSource>
11 <asp:Literal runat="server" ID="lblSeparator"> </asp:Literal>
12 <asp:Literal runat="server" ID="lblPageSizePicker"><small><b>Articles per page:</b></small></asp:Literal>
13 <asp:DropDownList ID="ddlArticlesPerPage" runat="server" AutoPostBack="True" OnSelectedIndexChanged="ddlArticlesPerPage_SelectedIndexChanged">
14 <asp:ListItem Value="5">5</asp:ListItem>
15 <asp:ListItem Value="10" Selected="True">10</asp:ListItem>
16 <asp:ListItem Value="25">25</asp:ListItem>
17 <asp:ListItem Value="50">50</asp:ListItem>
18 <asp:ListItem Value="100">100</asp:ListItem>
19 </asp:DropDownList>
20 <p></p>
21 <asp:GridView SkinID="Articles" ID="gvwArticles" runat="server" AllowPaging="True" AutoGenerateColumns="False"
22 DataKeyNames="ID" DataSourceID="objArticles" PageSize="10" ShowHeader="False"
23 EmptyDataText="b>" OnRowDataBound="gvwArticles_RowDataBound" OnRowCommand="gvwArticles_RowCommand">
24 <Columns>
25 <asp:TemplateField HeaderText="Article List (including those not yet published)">
26 <HeaderStyle HorizontalAlign="Left" />
27 <ItemTemplate>
28 <div class="articlebox">
29 <table cellpadding="0" cellspacing="0" style="width: 100%;"><tr><td>
30 <div class="articletitle">
31 <asp:HyperLink runat="server" ID="lnkTitle" CssClass="articletitle" Text='<%# Eval("Title") %>'
32 NavigateUrl='<%# "~/ShowArticle.aspx?ID=" + Eval("ID") %>'/>
33 <asp:Image runat="server" ID="imgKey" ImageUrl="~/Images/key.gif" AlternateText="Requires login"
34 Visible='<%# (bool)Eval("OnlyForMembers") && !Page.User.Identity.IsAuthenticated %>' />
35 <asp:Label runat="server" ID="lblNotApproved" Text="Not approved" SkinID="NotApproved" Visible='<%# !(bool)Eval("Approved") %>' />
36 </div>
37 </td>
38 <td style="text-align: right;">
39 <asp:Panel runat="server" ID="panEditArticle" Visible='<%# UserCanEdit %>'>
40 <asp:ImageButton runat="server" ID="btnApprove" ImageUrl="~/Images/Ok.gif"
41 CommandName="Approve" CommandArgument='<%# Eval("ID") %>' AlternateText="Approve article"
42 Visible='<%# !(bool)Eval("Approved") %>'
43 OnClientClick="if (confirm('Are you sure you want to approve this article?') == false) return false;" />
44
45 <asp:HyperLink runat="server" ID="lnkEdit" ToolTip="Edit article"
46 NavigateUrl='<%# "~/Admin/AddEditArticle.aspx?ID=" + Eval("ID") %>' ImageUrl="~/Images/Edit.gif" />
47
48 <asp:ImageButton runat="server" ID="btnDelete" ImageUrl="~/Images/Delete.gif"
49 CommandName="Delete" AlternateText="Delete article"
50 OnClientClick="if (confirm('Are you sure you want to delete this article?') == false) return false;" />
51 </asp:Panel>
52 </td></tr></table>
53 <b>Rating: </b>
54 <asp:Literal runat="server" ID="lblRating" Text='<%# Eval("Votes") + " user(s) have rated this article " %>' />
55 <mb:RatingDisplay runat="server" ID="ratDisplay" Value='<%# Eval("AverageRating") %>' />
56 <br />
57
58 <b>Posted by: </b> <asp:Literal runat="server" ID="lblAddedBy" Text='<%# Eval("AddedBy") %>' />,
59 on <asp:Literal runat="server" ID="lblAddedDate" Text='<%# Eval("ReleaseDate", "{0:d}") %>' />,
60 in category "<asp:Literal runat="server" ID="lblCategory" Text='<%# Eval("CategoryTitle") %>' />"
61 <br />
62 <b>Views: </b>
63 <asp:Literal runat="server" ID="lblViews" Text='<%# "this article has been read " + Eval("ViewCount") + " times" %>' />
64 <asp:Literal runat="server" ID="lblLocation" Visible='<%# Eval("Location").ToString().Length > 0 %>'
65 Text='<%# "<br /><b>Location: </b>" + Eval("Location") %>' />
66 <br />
67 <div class="articleabstract">
68 <b>Abstract: </b>
69 <asp:Literal runat="server" ID="lblAbstract" Text='<%# Eval("Abstract") %>' />
70 </div>
71 </div>
72 </ItemTemplate>
73 </asp:TemplateField>
74 </Columns>
75 <EmptyDataTemplate><b>No articles to show</b></EmptyDataTemplate>
76 </asp:GridView>
77 <asp:ObjectDataSource ID="objArticles" runat="server" DeleteMethod="DeleteArticle"
78 SelectMethod="GetArticles" SelectCountMethod="GetArticleCount" EnablePaging="True" TypeName="MB.TheBeerHouse.BLL.Articles.Article">
79 <DeleteParameters>
80 <asp:Parameter Name="id" Type="Int32" />
81 </DeleteParameters>
82 <SelectParameters>
83 <asp:Parameter DefaultValue="true" Name="publishedOnly" Type="Boolean" />
84 <asp:ControlParameter ControlID="ddlCategories" Name="categoryID" PropertyName="SelectedValue" Type="Int32" />
85 </SelectParameters>
86 </asp:ObjectDataSource>
\Controls\ArticleListing.ascx.cs1 using System;
2 using System.Data;
3 using System.Configuration;
4 using System.Collections;
5 using System.Web;
6 using System.Web.Security;
7 using System.Web.UI;
8 using System.Web.UI.WebControls;
9 using System.Web.UI.WebControls.WebParts;
10 using System.Web.UI.HtmlControls;
11 using MB.TheBeerHouse;
12 using MB.TheBeerHouse.UI;
13 using MB.TheBeerHouse.BLL.Articles;
14
15 namespace MB.TheBeerHouse.UI.Controls
16 {
17 public partial class ArticleListing : BaseWebPart
18 {
19 private bool _enableHighlighter = true;
20 public bool EnableHighlighter
21 {
22 get { return _enableHighlighter; }
23 set { _enableHighlighter = value; }
24 }
25
26 private bool _publishedOnly = true;
27 public bool PublishedOnly
28 {
29 get { return _publishedOnly; }
30 set
31 {
32 _publishedOnly = value;
33 objArticles.SelectParameters["publishedOnly"].DefaultValue = value.ToString();
34 }
35 }
36
37 private bool _showCategoryPicker = true;
38 public bool ShowCategoryPicker
39 {
40 get { return _showCategoryPicker; }
41 set
42 {
43 _showCategoryPicker = value;
44 ddlCategories.Visible = value;
45 lblCategoryPicker.Visible = value;
46 lblSeparator.Visible = value;
47 }
48 }
49
50 private bool _showPageSizePicker = true;
51 public bool ShowPageSizePicker
52 {
53 get { return _showPageSizePicker; }
54 set
55 {
56 _showPageSizePicker = value;
57 ddlArticlesPerPage.Visible = value;
58 lblPageSizePicker.Visible = value;
59 }
60 }
61
62 private bool _enablePaging = true;
63 public bool EnablePaging
64 {
65 get { return _enablePaging; }
66 set
67 {
68 _enablePaging = value;
69 gvwArticles.PagerSettings.Visible = value;
70 }
71 }
72
73 private bool _userCanEdit = false;
74 protected bool UserCanEdit
75 {
76 get { return _userCanEdit; }
77 set { _userCanEdit = value; }
78 }
79
80 private string _userCountry = "";
81 private string _userState = "";
82 private string _userCity = "";
83
84 protected void Page_Init(object sender, EventArgs e)
85 {
86 this.Page.RegisterRequiresControlState(this);
87
88 this.UserCanEdit = (this.Page.User.Identity.IsAuthenticated &&
89 (this.Page.User.IsInRole("Administrators") || this.Page.User.IsInRole("Editors")));
90
91 try
92 {
93 if (this.Page.User.Identity.IsAuthenticated)
94 {
95 _userCountry = this.Profile.Address.Country.ToLower();
96 _userState = this.Profile.Address.State.ToLower();
97 _userCity = this.Profile.Address.City.ToLower();
98 }
99 }
100 catch (Exception) { }
101 }
102
103 protected override void LoadControlState(object savedState)
104 {
105 object[] ctlState = (object[])savedState;
106 base.LoadControlState(ctlState[0]);
107 this.EnableHighlighter = (bool)ctlState[1];
108 this.PublishedOnly = (bool)ctlState[2];
109 this.ShowCategoryPicker = (bool)ctlState[3];
110 this.ShowPageSizePicker = (bool)ctlState[4];
111 this.EnablePaging = (bool)ctlState[5];
112 }
113
114 protected override object SaveControlState()
115 {
116 object[] ctlState = new object[6];
117 ctlState[0] = base.SaveControlState();
118 ctlState[1] = this.EnableHighlighter;
119 ctlState[2] = this.PublishedOnly;
120 ctlState[3] = this.ShowCategoryPicker;
121 ctlState[4] = this.ShowPageSizePicker;
122 ctlState[5] = this.EnablePaging;
123 return ctlState;
124 }
125
126 protected void Page_Load(object sender, EventArgs e)
127 {
128 if (!this.IsPostBack)
129 {
130 // preselect the category whose ID is passed in the querystring
131 if (!string.IsNullOrEmpty(this.Request.QueryString["CatID"]))
132 {
133 ddlCategories.DataBind();
134 ddlCategories.SelectedValue = this.Request.QueryString["CatID"];
135 }
136
137 // Set the page size as indicated in the config file. If an option for that size
138 // doesn't already exist, first create and then select it.
139 int pageSize = Globals.Settings.Articles.PageSize;
140 if (ddlArticlesPerPage.Items.FindByValue(pageSize.ToString()) == null)
141 ddlArticlesPerPage.Items.Add(new ListItem(pageSize.ToString(), pageSize.ToString()));
142 ddlArticlesPerPage.SelectedValue = pageSize.ToString();
143 gvwArticles.PageSize = pageSize;
144
145 gvwArticles.DataBind();
146 }
147 }
148
149 protected void ddlArticlesPerPage_SelectedIndexChanged(object sender, EventArgs e)
150 {
151 gvwArticles.PageSize = int.Parse(ddlArticlesPerPage.SelectedValue);
152 gvwArticles.PageIndex = 0;
153 gvwArticles.DataBind();
154 }
155
156 protected void ddlCategories_SelectedIndexChanged(object sender, EventArgs e)
157 {
158 gvwArticles.PageIndex = 0;
159 gvwArticles.DataBind();
160 }
161
162 protected void gvwArticles_RowDataBound(object sender, GridViewRowEventArgs e)
163 {
164 if (e.Row.RowType == DataControlRowType.DataRow &&
165 this.Page.User.Identity.IsAuthenticated && this.EnableHighlighter)
166 {
167 // hightlight the article row according to whether the current user's
168 // city, state or country is found in the article's city, state or country
169 Article article = (e.Row.DataItem as Article);
170 if (article.Country.ToLower() == _userCountry)
171 {
172 e.Row.CssClass = "highlightcountry";
173
174 if (Array.IndexOf<string>(
175 article.State.ToLower().Split(';'), _userState) > -1)
176 {
177 e.Row.CssClass = "highlightstate";
178
179 if (Array.IndexOf<string>(
180 article.City.ToLower().Split(';'), _userCity) > -1)
181 {
182 e.Row.CssClass = "highlightcity";
183 }
184 }
185 }
186 }
187 }
188
189 protected void gvwArticles_RowCommand(object sender, GridViewCommandEventArgs e)
190 {
191 if (e.CommandName == "Approve")
192 {
193 int articleID = int.Parse(e.CommandArgument.ToString());
194 Article.ApproveArticle(articleID);
195 gvwArticles.PageIndex = 0;
196 gvwArticles.DataBind();
197 }
198 }
199 }
200 }
\App_Code\BLL\Articles\Article.cs1 using System;
2 using System.Data;
3 using System.Configuration;
4 using System.Web;
5 using System.Web.Security;
6 using System.Web.UI;
7 using System.Web.UI.WebControls;
8 using System.Web.UI.WebControls.WebParts;
9 using System.Web.UI.HtmlControls;
10 using System.Collections.Generic;
11 using MB.TheBeerHouse.DAL;
12
13 namespace MB.TheBeerHouse.BLL.Articles
14 {
15 public class Article : BaseArticle
16 {
17 private int _categoryID = 0;
18 public int CategoryID
19 {
20 get { return _categoryID; }
21 set { _categoryID = value; }
22 }
23
24 private string _categoryTitle = "";
25 public string CategoryTitle
26 {
27 get { return _categoryTitle; }
28 private set { _categoryTitle = value; }
29 }
30
31 private Category _category = null;
32 public Category Category
33 {
34 get
35 {
36 if (_category == null)
37 _category = Category.GetCategoryByID(this.CategoryID);
38 return _category;
39 }
40 }
41
42 private string _title = "";
43 public string Title
44 {
45 get { return _title; }
46 set { _title = value; }
47 }
48
49 private string _abstract = "";
50 public string Abstract
51 {
52 get { return _abstract; }
53 set { _abstract = value; }
54 }
55
56 private string _body = null;
57 public string Body
58 {
59 get
60 {
61 if (_body == null)
62 _body = SiteProvider.Articles.GetArticleBody(this.ID);
63 return _body;
64 }
65 set { _body = value; }
66 }
67
68 private string _country = "";
69 public string Country
70 {
71 get { return _country; }
72 set { _country = value; }
73 }
74
75 private string _state = "";
76 public string State
77 {
78 get { return _state; }
79 set { _state = value; }
80 }
81
82 private string _city = "";
83 public string City
84 {
85 get { return _city; }
86 set { _city = value; }
87 }
88
89 public string Location
90 {
91 get
92 {
93 string location = this.City.Split(';')[0];
94 if (this.State.Length > 0)
95 {
96 if (location.Length > 0)
97 location += ", ";
98 location += this.State.Split(';')[0];
99 }
100 if (this.Country.Length > 0)
101 {
102 if (location.Length > 0)
103 location += ", ";
104 location += this.Country;
105 }
106 return location;
107 }
108 }
109
110 private DateTime _releaseDate = DateTime.Now;
111 public DateTime ReleaseDate
112 {
113 get { return _releaseDate; }
114 set { _releaseDate = value; }
115 }
116
117 private DateTime _expireDate = DateTime.MaxValue;
118 public DateTime ExpireDate
119 {
120 get { return _expireDate; }
121 set { _expireDate = value; }
122 }
123
124 private bool _approved = true;
125 public bool Approved
126 {
127 get { return _approved; }
128 set { _approved = value; }
129 }
130
131 private bool _listed = true;
132 public bool Listed
133 {
134 get { return _listed; }
135 set { _listed = value; }
136 }
137
138 private bool _commentsEnabled = true;
139 public bool CommentsEnabled
140 {
141 get { return _commentsEnabled; }
142 set { _commentsEnabled = value; }
143 }
144
145 private bool _onlyForMembers = true;
146 public bool OnlyForMembers
147 {
148 get { return _onlyForMembers; }
149 set { _onlyForMembers = value; }
150 }
151
152 private int _viewCount = 0;
153 public int ViewCount
154 {
155 get { return _viewCount; }
156 private set { _viewCount = value; }
157 }
158
159 private int _votes = 0;
160 public int Votes
161 {
162 get { return _votes; }
163 private set { _votes = value; }
164 }
165
166 private int _totalRating = 0;
167 public int TotalRating
168 {
169 get { return _totalRating; }
170 private set { _totalRating = value; }
171 }
172
173 public double AverageRating
174 {
175 get
176 {
177 if (this.Votes >= 1)
178 return ((double)this.TotalRating / (double)this.Votes);
179 else
180 return 0.0;
181 }
182 }
183
184 private List _comments = null;
185 public List Comments
186 {
187 get
188 {
189 if (_comments==null)
190 _comments = Comment.GetComments(this.ID, 0, BizObject.MAXROWS);
191 return _comments;
192 }
193 }
194
195 public bool Published
196 {
197 get
198 {
199 return (this.Approved && this.ReleaseDate <= DateTime.Now &&
200 this.ExpireDate > DateTime.Now);
201 }
202 }
203
204 public Article(int id, DateTime addedDate, string addedBy,
205 int categoryID, string categoryTitle, string title, string artabstract,
206 string body, string country, string state, string city,
207 DateTime releaseDate, DateTime expireDate, bool approved,
208 bool listed, bool commentsEnabled, bool onlyForMembers,
209 int viewCount, int votes, int totalRating)
210 {
211 this.ID = id;
212 this.AddedDate = addedDate;
213 this.AddedBy = addedBy;
214 this.CategoryID = categoryID;
215 this.CategoryTitle = categoryTitle;
216 this.Title = title;
217 this.Abstract = artabstract;
218 this.Body = body;
219 this.Country = country;
220 this.State = state;
221 this.City = city;
222 this.ReleaseDate = releaseDate;
223 this.ExpireDate = expireDate;
224 this.Approved = approved;
225 this.Listed = listed;
226 this.CommentsEnabled = commentsEnabled;
227 this.OnlyForMembers = onlyForMembers;
228 this.ViewCount = viewCount;
229 this.Votes = votes;
230 this.TotalRating = totalRating;
231 }
232
233 public bool Delete()
234 {
235 bool success = Article.DeleteArticle(this.ID);
236 if (success)
237 this.ID = 0;
238 return success;
239 }
240
241 public bool Update()
242 {
243 return Article.UpdateArticle(this.ID, this.CategoryID, this.Title,
244 this.Abstract, this.Body, this.Country, this.State, this.City,
245 this.ReleaseDate, this.ExpireDate, this.Approved, this.Listed,
246 this.CommentsEnabled, this.OnlyForMembers);
247 }
248
249 public bool Approve()
250 {
251 bool success = Article.ApproveArticle(this.ID);
252 if (success)
253 this.Approved = true;
254 return success;
255 }
256
257 public bool IncrementViewCount()
258 {
259 return Article.IncrementArticleViewCount(this.ID);
260 }
261
262 public bool Rate(int rating)
263 {
264 return Article.RateArticle(this.ID, rating);
265 }
266
267 /***********************************
268 * Static methods
269 ************************************/
270
271 /// <summary>
272 /// Returns a collection with all articles
273 /// </summary>
274 public static List GetArticles()
275 {
276 return GetArticles(0, BizObject.MAXROWS);
277 }
278 public static List GetArticles(int startRowIndex, int maximumRows)
279 {
280 List articles = null;
281 string key = "Articles_Articles_" + startRowIndex.ToString() + "_" + maximumRows.ToString();
282
283 if (BaseArticle.Settings.EnableCaching && BizObject.Cache[key] != null)
284 {
285 articles = (List)BizObject.Cache[key];
286 }
287 else
288 {
289 List recordset = SiteProvider.Articles.GetArticles(
290 GetPageIndex(startRowIndex, maximumRows), maximumRows);
291 articles = GetArticleListFromArticleDetailsList(recordset);
292 BaseArticle.CacheData(key, articles);
293 }
294 return articles;
295 }
296
297 /// <summary>
298 /// Returns a collection with all articles for the specified category
299 /// </summary>
300 public static List GetArticles(int categoryID)
301 {
302 return GetArticles(categoryID, 0, BizObject.MAXROWS);
303 }
304 public static List GetArticles(int categoryID, int startRowIndex, int maximumRows)
305 {
306 if (categoryID <= 0)
307 return GetArticles(startRowIndex, maximumRows);
308
309 List articles = null;
310 string key = "Articles_Articles_" + categoryID.ToString() + "_" + startRowIndex.ToString() + "_" + maximumRows.ToString();
311
312 if (BaseArticle.Settings.EnableCaching && BizObject.Cache[key] != null)
313 {
314 articles = (List)BizObject.Cache[key];
315 }
316 else
317 {
318 List recordset = SiteProvider.Articles.GetArticles(categoryID,
319 GetPageIndex(startRowIndex, maximumRows), maximumRows);
320 articles = GetArticleListFromArticleDetailsList(recordset);
321 BaseArticle.CacheData(key, articles);
322 }
323 return articles;
324 }
325
326 /// <summary>
327 /// Returns the number of total articles
328 /// </summary>
329 public static int GetArticleCount()
330 {
331 int articleCount = 0;
332 string key = "Articles_ArticleCount";
333
334 if (BaseArticle.Settings.EnableCaching && BizObject.Cache[key] != null)
335 {
336 articleCount = (int)BizObject.Cache[key];
337 }
338 else
339 {
340 articleCount = SiteProvider.Articles.GetArticleCount();
341 BaseArticle.CacheData(key, articleCount);
342 }
343 return articleCount;
344 }
345
346 /// <summary>
347 /// Returns the number of total articles for the specified category
348 /// </summary>
349 public static int GetArticleCount(int categoryID)
350 {
351 if (categoryID <= 0)
352 return GetArticleCount();
353
354 int articleCount = 0;
355 string key = "Articles_ArticleCount_" + categoryID.ToString();
356
357 if (BaseArticle.Settings.EnableCaching && BizObject.Cache[key] != null)
358 {
359 articleCount = (int)BizObject.Cache[key];
360 }
361 else
362 {
363 articleCount = SiteProvider.Articles.GetArticleCount(categoryID);
364 BaseArticle.CacheData(key, articleCount);
365 }
366 return articleCount;
367 }
368
369 /// <summary>
370 /// Returns a collection with all published articles
371 /// </summary>
372 public static List GetArticles(bool publishedOnly)
373 {
374 return GetArticles(publishedOnly, 0, BizObject.MAXROWS);
375 }
376 public static List GetArticles(bool publishedOnly, int startRowIndex, int maximumRows)
377 {
378 if (!publishedOnly)
379 return GetArticles(startRowIndex, maximumRows);
380
381 List articles = null;
382 string key = "Articles_Articles_" + publishedOnly.ToString() + "_" + startRowIndex.ToString() + "_" + maximumRows.ToString();
383
384 if (BaseArticle.Settings.EnableCaching && BizObject.Cache[key] != null)
385 {
386 articles = (List)BizObject.Cache[key];
387 }
388 else
389 {
390 List recordset = SiteProvider.Articles.GetPublishedArticles(DateTime.Now,
391 GetPageIndex(startRowIndex, maximumRows), maximumRows);
392 articles = GetArticleListFromArticleDetailsList(recordset);
393 BaseArticle.CacheData(key, articles);
394 }
395 return articles;
396 }
397
398 /// <summary>
399 /// Returns a collection with all published articles for the specified category
400 /// </summary>
401 public static List GetArticles(bool publishedOnly, int categoryID)
402 {
403 return GetArticles(publishedOnly, categoryID, 0, BizObject.MAXROWS);
404 }
405 public static List GetArticles(bool publishedOnly, int categoryID, int startRowIndex, int maximumRows)
406 {
407 if (!publishedOnly)
408 return GetArticles(categoryID, startRowIndex, maximumRows);
409
410 if (categoryID <= 0)
411 return GetArticles(publishedOnly, startRowIndex, maximumRows);
412
413 List articles = null;
414 string key = "Articles_Articles_" + publishedOnly.ToString() + "_" + categoryID.ToString() + "_" + startRowIndex.ToString() + "_" + maximumRows.ToString();
415
416 if (BaseArticle.Settings.EnableCaching && BizObject.Cache[key] != null)
417 {
418 articles = (List)BizObject.Cache[key];
419 }
420 else
421 {
422 List recordset = SiteProvider.Articles.GetPublishedArticles(
423 categoryID, DateTime.Now,
424 GetPageIndex(startRowIndex, maximumRows), maximumRows);
425 articles = GetArticleListFromArticleDetailsList(recordset);
426 BaseArticle.CacheData(key, articles);
427 }
428 return articles;
429 }
430
431 /// <summary>
432 /// Returns the number of total published articles
433 /// </summary>
434 public static int GetArticleCount(bool publishedOnly)
435 {
436 if (publishedOnly)
437 return GetArticleCount();
438
439 int articleCount = 0;
440 string key = "Articles_ArticleCount_" + publishedOnly.ToString();
441
442 if (BaseArticle.Settings.EnableCaching && BizObject.Cache[key] != null)
443 {
444 articleCount = (int)BizObject.Cache[key];
445 }
446 else
447 {
448 articleCount = SiteProvider.Articles.GetPublishedArticleCount(DateTime.Now);
449 BaseArticle.CacheData(key, articleCount);
450 }
451 return articleCount;
452 }
453
454 /// <summary>
455 /// Returns the number of total published articles for the specified category
456 /// </summary>
457 public static int GetArticleCount(bool publishedOnly, int categoryID)
458 {
459 if (!publishedOnly)
460 return GetArticleCount(categoryID);
461
462 if (categoryID <= 0)
463 return GetArticleCount(publishedOnly);
464
465 int articleCount = 0;
466 string key = "Articles_ArticleCount_" + publishedOnly.ToString() + "_" + categoryID.ToString();
467
468 if (BaseArticle.Settings.EnableCaching && BizObject.Cache[key] != null)
469 {
470 articleCount = (int)BizObject.Cache[key];
471 }
472 else
473 {
474 articleCount = SiteProvider.Articles.GetPublishedArticleCount(categoryID, DateTime.Now);
475 BaseArticle.CacheData(key, articleCount);
476 }
477 return articleCount;
478 }
479
480 /// <summary>
481 /// Returns an Article object with the specified ID
482 /// </summary>
483 public static Article GetArticleByID(int articleID)
484 {
485 Article article = null;
486 string key = "Articles_Article_" + articleID.ToString();
487
488 if (BaseArticle.Settings.EnableCaching && BizObject.Cache[key] != null)
489 {
490 article = (Article)BizObject.Cache[key];
491 }
492 else
493 {
494 article = GetArticleFromArticleDetails(SiteProvider.Articles.GetArticleByID(articleID));
495 BaseArticle.CacheData(key, article);
496 }
497 return article;
498 }
499
500 /// <summary>
501 /// Updates an existing article
502 /// </summary>
503 public static bool UpdateArticle(int id, int categoryID, string title,
504 string Abstract, string body, string country, string state, string city,
505 DateTime releaseDate, DateTime expireDate, bool approved, bool listed,
506 bool commentsEnabled, bool onlyForMembers)
507 {
508 title = BizObject.ConvertNullToEmptyString(title);
509 Abstract = BizObject.ConvertNullToEmptyString(Abstract);
510 body = BizObject.ConvertNullToEmptyString(body);
511 country = BizObject.ConvertNullToEmptyString(country);
512 state = BizObject.ConvertNullToEmptyString(state);
513 city = BizObject.ConvertNullToEmptyString(city);
514
515 if (releaseDate == DateTime.MinValue)
516 releaseDate = DateTime.Now;
517 if (expireDate == DateTime.MinValue)
518 expireDate = DateTime.MaxValue;
519
520 ArticleDetails record = new ArticleDetails(id, DateTime.Now, "", categoryID,
521 "", title, Abstract, body, country, state, city, releaseDate, expireDate,
522 approved, listed, commentsEnabled, onlyForMembers, 0, 0, 0);
523 bool ret = SiteProvider.Articles.UpdateArticle(record);
524
525 BizObject.PurgeCacheItems("articles_article_" + id.ToString());
526 BizObject.PurgeCacheItems("articles_articles");
527 return ret;
528 }
529
530 /// <summary>
531 /// Creates a new article
532 /// </summary>
533 public static int InsertArticle(int categoryID, string title, string Abstract,
534 string body, string country, string state, string city, DateTime releaseDate, DateTime expireDate,
535 bool approved, bool listed, bool commentsEnabled, bool onlyForMembers)
536 {
537 // ensure that the "approved" option is false if the current user is not
538 // an administrator or a editor (it may be a contributor for example)
539 bool canApprove = (BizObject.CurrentUser.IsInRole("Administrators") || BizObject.CurrentUser.IsInRole("Editors"));
540 if (!canApprove)
541 approved = false;
542
543 title = BizObject.ConvertNullToEmptyString(title);
544 Abstract = BizObject.ConvertNullToEmptyString(Abstract);
545 body = BizObject.ConvertNullToEmptyString(body);
546 country = BizObject.ConvertNullToEmptyString(country);
547 state = BizObject.ConvertNullToEmptyString(state);
548 city = BizObject.ConvertNullToEmptyString(city);
549
550 if (releaseDate == DateTime.MinValue)
551 releaseDate = DateTime.Now;
552 if (expireDate == DateTime.MinValue)
553 expireDate = DateTime.MaxValue;
554
555 ArticleDetails record = new ArticleDetails(0, DateTime.Now, BizObject.CurrentUserName,
556 categoryID, "", title, Abstract, body, country, state, city, releaseDate, expireDate,
557 approved, listed, commentsEnabled, onlyForMembers, 0, 0, 0);
558 int ret = SiteProvider.Articles.InsertArticle(record);
559
560 BizObject.PurgeCacheItems("articles_article");
561 return ret;
562 }
563
564 /// <summary>
565 /// Deletes an existing article
566 /// </summary>
567 public static bool DeleteArticle(int id)
568 {
569 bool ret = SiteProvider.Articles.DeleteArticle(id);
570 new RecordDeletedEvent("article", id, null).Raise();
571 BizObject.PurgeCacheItems("articles_article");
572 return ret;
573 }
574
575 /// <summary>
576 /// Approves an existing article
577 /// </summary>
578 public static bool ApproveArticle(int id)
579 {
580 bool ret = SiteProvider.Articles.ApproveArticle(id);
581 BizObject.PurgeCacheItems("articles_article_" + id.ToString());
582 BizObject.PurgeCacheItems("articles_articles");
583 return ret;
584 }
585
586 /// <summary>
587 /// Increments an article's view count
588 /// </summary>
589 public static bool IncrementArticleViewCount(int id)
590 {
591 return SiteProvider.Articles.IncrementArticleViewCount(id);
592 }
593
594 /// <summary>
595 /// Increments an article's view count
596 /// </summary>
597 public static bool RateArticle(int id, int rating)
598 {
599 return SiteProvider.Articles.RateArticle(id, rating);
600 }
601
602 /// <summary>
603 /// Returns a Article object filled with the data taken from the input ArticleDetails
604 /// </summary>
605 private static Article GetArticleFromArticleDetails(ArticleDetails record)
606 {
607 if (record == null)
608 return null;
609 else
610 {
611 return new Article(record.ID, record.AddedDate, record.AddedBy,
612 record.CategoryID, record.CategoryTitle, record.Title, record.Abstract, record.Body,
613 record.Country, record.State, record.City, record.ReleaseDate, record.ExpireDate,
614 record.Approved, record.Listed, record.CommentsEnabled, record.OnlyForMembers,
615 record.ViewCount, record.Votes, record.TotalRating);
616 }
617 }
618
619 /// <summary>
620 /// Returns a list of Article objects filled with the data taken from the input list of ArticleDetails
621 /// </summary>
622 private static List GetArticleListFromArticleDetailsList(List recordset)
623 {
624 List articles = new List();
625 foreach (ArticleDetails record in recordset)
626 articles.Add(GetArticleFromArticleDetails(record));
627 return articles;
628 }
629 }
630 }
\App_Code\BLL\Articles\BaseArticle.cs1 using System;
2 using System.Data;
3 using System.Configuration;
4 using System.Web;
5 using System.Web.Security;
6 using System.Web.UI;
7 using System.Web.UI.WebControls;
8 using System.Web.UI.WebControls.WebParts;
9 using System.Web.UI.HtmlControls;
10 using System.Collections.Generic;
11 using MB.TheBeerHouse.DAL;
12
13 namespace MB.TheBeerHouse.BLL.Articles
14 {
15 public abstract class BaseArticle : BizObject
16 {
17 private int _id = 0;
18 public int ID
19 {
20 get { return _id; }
21 protected set { _id = value; }
22 }
23
24 private DateTime _addedDate = DateTime.Now;
25 public DateTime AddedDate
26 {
27 get { return _addedDate; }
28 protected set { _addedDate = value; }
29 }
30
31 private string _addedBy = "";
32 public string AddedBy
33 {
34 get { return _addedBy; }
35 protected set { _addedBy = value; }
36 }
37
38 protected static ArticlesElement Settings
39 {
40 get { return Globals.Settings.Articles; }
41 }
42
43 /// <summary>
44 /// Cache the input data, if caching is enabled
45 /// </summary>
46 protected static void CacheData(string key, object data)
47 {
48 if (Settings.EnableCaching && data != null)
49 {
50 BizObject.Cache.Insert(key, data, null,
51 DateTime.Now.AddSeconds(Settings.CacheDuration), TimeSpan.Zero);
52 }
53 }
54 }
55 }
\App_Code\BLL\BizObject.cs1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.Data;
5 using System.Configuration;
6 using System.Web;
7 using System.Web.Security;
8 using System.Web.UI;
9 using System.Web.Caching;
10 using System.Web.UI.WebControls;
11 using System.Web.UI.WebControls.WebParts;
12 using System.Web.UI.HtmlControls;
13 using System.Security.Principal;
14 using MB.TheBeerHouse.DAL;
15
16 namespace MB.TheBeerHouse.BLL
17 {
18 public abstract class BizObject
19 {
20 protected const int MAXROWS = int.MaxValue;
21
22 protected static Cache Cache
23 {
24 get { return HttpContext.Current.Cache; }
25 }
26
27 protected static IPrincipal CurrentUser
28 {
29 get { return HttpContext.Current.User; }
30 }
31
32 protected static string CurrentUserName
33 {
34 get
35 {
36 string userName = "";
37 if (HttpContext.Current.User.Identity.IsAuthenticated)
38 userName = HttpContext.Current.User.Identity.Name;
39 return userName;
40 }
41 }
42
43 protected static string CurrentUserIP
44 {
45 get { return HttpContext.Current.Request.UserHostAddress; }
46 }
47
48 protected static int GetPageIndex(int startRowIndex, int maximumRows)
49 {
50 if (maximumRows <= 0)
51 return 0;
52 else
53 return (int)Math.Floor((double)startRowIndex / (double)maximumRows);
54 }
55
56 protected static string ConvertNullToEmptyString(string input)
57 {
58 return (input == null ? "" : input);
59 }
60
61 /// <summary>
62 /// Remove from the ASP.NET cache all items whose key starts with the input prefix
63 /// </summary>
64 protected static void PurgeCacheItems(string prefix)
65 {
66 prefix = prefix.ToLower();
67 List<string> itemsToRemove = new List<string>();
68
69 IDictionaryEnumerator enumerator = BizObject.Cache.GetEnumerator();
70 while (enumerator.MoveNext())
71 {
72 if (enumerator.Key.ToString().ToLower().StartsWith(prefix))
73 itemsToRemove.Add(enumerator.Key.ToString());
74 }
75
76 foreach (string itemToRemove in itemsToRemove)
77 BizObject.Cache.Remove(itemToRemove);
78 }
79 }
80 }