Mini Kabibi Habibi
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using DevExpress.Web.ASPxEditors;
using DevExpress.Web.ASPxClasses;
public partial class VideoView : System.Web.UI.UserControl {
const string
UserCommentsSessionKey = "398f9710-5213-4d77-b3eb-d2a022486bd2",
InvalidNameErrorText = "Name must be non-empty and its length must not exceed 40 characters.",
InvalidCommentErrorText = "Comment must be non-empty and its length must not exceed 5000 characters.";
const int
MaxUserNameLength = 40,
MaxCommentLength = 5000;
public string VideoTitle { get; set; }
protected List<Comment> UserComments {
get {
if(Session[UserCommentsSessionKey] == null)
Session[UserCommentsSessionKey] = new List<Comment>();
return Session[UserCommentsSessionKey] as List<Comment>;
}
}
protected void InitializeTagList(Video video) {
rpTags.DataSource = video.TagVideoRelations
.Select(r => new {
Name = r.Tag.Name,
UrlName = Server.UrlEncode(r.Tag.Name)
})
.AsQueryable();
rpTags.DataBind();
}
protected void InitializeComments(Video video) {
var persistentComments = video.Comments.AsQueryable();
var userComments = UserComments
.Where(c => c.VideoID == video.ID)
.AsQueryable();
rpComments.DataSource = persistentComments
.Union(userComments)
.OrderBy(c => c.AddedAt)
.Select(c => new {
UserName = c.UserName,
UserAvatarID = c.UserAvatarID,
AddedAt = string.Format("{0:d}", c.AddedAt),
Text = c.Text
});
rpComments.DataBind();
}
protected void InitializeRelatedVideos(Video video) {
var videoTagNames = video.TagVideoRelations
.Select(r => r.Tag.Name)
.ToList();
rpRelatedVideos.DataSource = new VideoPortalDataContext().Videos
.Where(v => v.ID != video.ID)
//Map
.SelectMany(v => v.TagVideoRelations, (v, r) => new {
Video = v,
TagName = r.Tag.Name
})
.Where(vt => videoTagNames.Contains(vt.TagName))
//Reduce
.GroupBy(vt => vt.Video.ID, vt => vt.Video, (i, vc) => new {
Video = vc.First(),
Relevance = vc.Count()
})
.OrderByDescending(vr => vr.Relevance)
.AsEnumerable()
.Select(vr => new {
ID = vr.Video.ID,
Title = vr.Video.Title,
Url = ResolveUrl("~/Watch/" + Server.UrlEncode(vr.Video.Title))
});
rpRelatedVideos.DataBind();
}
protected override void OnInit(EventArgs e) {
base.OnInit(e);
}
protected void Page_Load(object sender, EventArgs e) {
var video = new VideoPortalDataContext().Videos
.Where(v => v.Title == VideoTitle)
.First();
InitializeTagList(video);
InitializeComments(video);
InitializeRelatedVideos(video);
videoPlaceholder.InnerHtml = video.EmbeddedCode;
videoTitleControl.InnerText = VideoTitle;
product.InnerHtml = video.Product;
published.InnerHtml = string.Format("{0:d}", video.CreationDate);
description.InnerHtml = video.Description;
if(!cpComments.IsCallback) {
commentEditor.Html = string.Empty;
tbName.Text = string.Empty;
}
}
protected bool ValidateComment(string userName, string text) {
var valid = true;
if(string.IsNullOrEmpty(userName) || userName.Length > MaxUserNameLength) {
errorText.InnerText = InvalidNameErrorText;
valid = false;
}
if(string.IsNullOrEmpty(text) || text.Length > MaxCommentLength) {
if(!valid)
errorText.InnerText += "\n";
errorText.InnerText += InvalidCommentErrorText;
valid = false;
}
errorFrame.Visible = !valid;
return valid;
}
protected void cpComments_Callback(object sender, CallbackEventArgsBase e) {
var video = new VideoPortalDataContext().Videos
.Where(v => v.Title == VideoTitle)
.First();
var userName = tbName.Text.Trim();
var text = e.Parameter.Trim();
if(!ValidateComment(userName, text))
return;
Comment comment = new Comment() {
VideoID = video.ID,
UserAvatarID = 0,
UserName = Server.HtmlEncode(userName),
Text = commentEditor.Html,
AddedAt = DateTime.Now
};
UserComments.Add(comment);
InitializeComments(video);
commentEditor.Html = string.Empty;
tbName.Text = string.Empty;
}
}