/Mindfor.WebMP/CmsController.cs
C# | 493 lines | 295 code | 58 blank | 140 comment | 49 complexity | edc69622c343cd853cc34643a7a02c3d MD5 | raw file
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Drawing.Imaging;
- using System.Globalization;
- using System.IO;
- using System.Linq;
- using System.Net.Mail;
- using System.Text;
- using System.Web;
- using System.Web.Mvc;
- using System.Web.Routing;
- using System.Xml.Linq;
- using FreeImageAPI;
- using Mindfor.Web.Config;
- using Mindfor.Web.Data;
- using NHibernate;
- using NHibernate.Linq;
- using Mindfor.Web.Models;
- using System.ComponentModel;
- using System.Linq.Expressions;
- namespace Mindfor.Web
- {
- /// <summary>
- /// Base CMS controller which implements cms options loading, such as configuration and data provider.
- /// </summary>
- public abstract class CmsController : Controller
- {
- ISession m_data;
- Uri m_siteUri;
- SmtpClient m_smtp;
-
- /// <summary>
- /// Gets data session.
- /// </summary>
- public ISession Data
- {
- get
- {
- if (m_data == null)
- {
- m_data = CmsApplication.DataProvider.GetCurrentSession();
- if (m_data == null)
- throw new InvalidOperationException("Can not get current data session.");
- }
- return m_data;
- }
- }
- /// <summary>
- /// Gets whether running in debug mode.
- /// </summary>
- public bool IsDebug
- {
- get
- {
- #if DEBUG
- return true;
- #else
- return false;
- #endif
- }
- }
- /// <summary>
- /// Gets site url that is determined from current request.
- /// </summary>
- public Uri SiteUrl
- {
- get
- {
- if (m_siteUri == null)
- {
- Uri requestUrl = this.Request.Url;
- string siteUrl = requestUrl.AbsoluteUri.Substring(0,
- requestUrl.AbsoluteUri.Length - requestUrl.PathAndQuery.Length);
- m_siteUri = new Uri(siteUrl, UriKind.Absolute);
- }
- return m_siteUri;
- }
- }
- /// <summary>
- /// Gets controller module.
- /// </summary>
- public ModuleBase Module { get; private set; }
- /// <summary>
- /// Gets current authenticated user. Returns null if user is anonymous.
- /// </summary>
- public new User User { get; private set; }
- /// <summary>
- /// Gets current request language.
- /// </summary>
- public Language Language { get; private set; }
- /// <summary>
- /// Gets whether user is authenticated.
- /// </summary>
- public bool IsAuthenticated
- {
- get { return this.User != null; }
- }
- #region For page module
- /// <summary>
- /// Gets current request page.
- /// </summary>
- public Page CurrentPage
- {
- get { return ViewData["Global.CurrentPage"] as Page; }
- }
- /// <summary>
- /// Gets current page text.
- /// </summary>
- public PageText CurrentPageText
- {
- get { return ViewData["Global.CurrentPageText"] as PageText; }
- }
- /// <summary>
- /// Gets main action name if current action is sub-action.
- /// If current action is main action then returns null.
- /// </summary>
- public string MainActionName
- {
- get { return ViewData["Global.MainActionName"] as string; }
- }
- /// <summary>
- /// Gets whether current action is main- or sub-.
- /// If false, then CurrentPage and CurrentPageText is taken from main action.
- /// </summary>
- public bool IsMainAction
- {
- get { return MainActionName == null; }
- }
- /// <summary>
- /// Gets page title.
- /// </summary>
- public PageTitleCollection PageTitle { get; private set; }
- #endregion
- /// <summary>
- /// Initializes new instance.
- /// </summary>
- public CmsController()
- {
- }
- /// <summary>
- /// Initializes class before invoke action.
- /// </summary>
- /// <param name="requestContext">Request context.</param>
- protected override void Initialize(RequestContext requestContext)
- {
- // base initialize
- base.Initialize(requestContext);
- // get module
- string moduleName = requestContext.RouteData.Values["module"] as string;
- if (moduleName != null)
- {
- Module = ModuleFactory.Default.Modules[moduleName];
- HttpContext.Items["module"] = Module;
- }
- // get current user
- if (base.User != null && base.User.Identity != null &&
- base.User.Identity.IsAuthenticated)
- User = Data.Query<User>().GetUser(base.User.Identity.Name);
-
- // get current language and culture
- string langUrlName = (string)requestContext.RouteData.Values["lang"];
- if (String.IsNullOrEmpty(langUrlName))
- langUrlName = CmsConfig.Default.DefaultLanguage;
- if (!String.IsNullOrEmpty(langUrlName))
- Language = Data.Query<Language>().FirstOrDefault(r => r.UrlName == langUrlName);
- if (Language == null)
- Language = Data.Query<Language>().FirstOrDefault();
-
- if (Language != null)
- {
- CultureInfo culture = null;
- try
- {
- culture = CultureInfo.GetCultureInfo(Language.Culture);
- }
- catch (Exception ex)
- {
- throw new InvalidOperationException("Cannot find \"" + Language.Culture + "\" culture.", ex);
- }
- System.Threading.Thread.CurrentThread.CurrentCulture = culture;
- System.Threading.Thread.CurrentThread.CurrentUICulture = culture;
- }
-
- ControllerContext.HttpContext.Trace.Write("CmsController", "Initialize end");
- }
- /// <summary>
- /// Adds error to local log and mindfor server log.
- /// </summary>
- /// <param name="ex">Error to add to logs.</param>
- protected void LogError(Exception ex)
- {
- // log local
- try
- {
- Log log = new Log(ex);
- using (ITransaction t = Data.BeginTransaction())
- {
- Data.Save(log);
- t.Commit();
- }
- }
- catch { }
- // log to server
- if (CmsConfig.Default.ApplicationId.HasValue)
- Mindfor.Error.ErrorProxy.SubmitSafe(CmsConfig.Default.ApplicationId.Value, ex);
- }
- /// <summary>
- /// Sets model complex property to value that was loaded from DataProvider by primary key
- /// specified in value provider.
- /// </summary>
- /// <param name="model">Model to update.</param>
- /// <param name="propertyName">Complex property that references another type.</param>
- /// <param name="primaryKeyName">Primary key name in complex property.</param>
- /// <exception cref="TypeLoadException">Occures when complex property is not found.</exception>
- protected void UpdateModelReference(object model, string propertyName, string primaryKeyName)
- {
- if (String.IsNullOrEmpty(propertyName))
- throw new ArgumentNullException(propertyName);
- if (String.IsNullOrEmpty(primaryKeyName))
- throw new ArgumentNullException(primaryKeyName);
- // find properties
- PropertyDescriptor propDescriptor = TypeDescriptor.GetProperties(model)[propertyName];
- if (propDescriptor == null)
- throw new TypeLoadException(String.Format("Can not find property \"{0}\".", propertyName));
- PropertyDescriptor primaryPropDescriptor = TypeDescriptor.GetProperties(propDescriptor.PropertyType)[primaryKeyName];
- if (primaryPropDescriptor == null)
- throw new TypeLoadException(String.Format("Can not find property \"{0}\".", primaryKeyName));
- // get complex property value
- string key = propertyName + "." + primaryKeyName;
- ValueProviderResult valueProviderResult = ValueProvider.GetValue(key);
- if (valueProviderResult != null)
- {
- object id = valueProviderResult.ConvertTo(primaryPropDescriptor.PropertyType);
- if (id != null)
- {
- object reference = Data.Get(propDescriptor.PropertyType, id);
- propDescriptor.SetValue(model, reference);
- }
- }
- }
- /// <summary>
- /// Sets model complex property to value that was loaded from DataProvider by primary key
- /// specified in value provider.
- /// </summary>
- /// <param name="model">Model to update.</param>
- /// <param name="propertyExpression">Lambda expression to complex property that references another type.</param>
- /// <param name="primaryKeyExpression">Lambda expression to primary key in complex property.</param>
- /// <exception cref="TypeLoadException">Occures when complex property is not found.</exception>
- protected void UpdateModelReference<TModel, TProperty, TKey>(TModel model, Expression<Func<TModel, TProperty>> propertyExpression, Expression<Func<TProperty, TKey>> primaryKeyExpression)
- {
- string propertyName = ExpressionHelper.GetExpressionText(propertyExpression);
- string primaryKeyName = ExpressionHelper.GetExpressionText(primaryKeyExpression);
- UpdateModelReference(model, propertyName, primaryKeyName);
- }
- /// <summary>
- /// Sets model complex property to value that was loaded from DataProvider by primary key "Id".
- /// </summary>
- /// <param name="model">Model to update.</param>
- /// <param name="propertyExpression">Lambda expression to complex property that references another type.</param>
- /// <exception cref="TypeLoadException">Occures when complex property is not found.</exception>
- protected void UpdateModelReference<TModel, TProperty>(TModel model, Expression<Func<TModel, TProperty>> propertyExpression)
- {
- string propertyName = ExpressionHelper.GetExpressionText(propertyExpression);
- UpdateModelReference(model, propertyName, "Id");
- }
- #region Custom ActionResults
- /// <summary>
- /// Returns <see cref="FileContentResult"/> which sends image to response.
- /// </summary>
- /// <param name="image">Image to send to response.</param>
- protected virtual FileResult Image(Image image)
- {
- return Image(image, null, -1, -1);
- }
- /// <summary>
- /// Returns <see cref="FileStreamResult"/> with xml document data.
- /// </summary>
- /// <param name="xmlDocument">Xml document to render.</param>
- protected virtual XResult Xml(XDocument xmlDocument)
- {
- return new XResult(xmlDocument);
- }
- /// <summary>
- /// Returns <see cref="FileStreamResult"/> with xml document data.
- /// </summary>
- /// <param name="rootElement">Xml root element.</param>
- protected virtual XResult Xml(XElement rootElement)
- {
- return new XResult(rootElement);
- }
- /// <summary>
- /// Returns <see cref="FileContentResult"/>, which sends image to response.
- /// Image size changes proportional.
- /// </summary>
- /// <param name="image">Image to send to response.</param>
- /// <param name="name">Image file name.</param>
- /// <param name="maxWidth">Max width of image. Use -1 not to analyse width.</param>
- /// <param name="maxHeight">Max height of image. Use -1 not to analyse height.</param>
- protected virtual FileResult Image(Image image, string name, int maxWidth, int maxHeight)
- {
- if (image == null)
- return null;
- const int maxOriginalArea = 100 * 100;
- const int outputImageQuality = 80;
- Image sizedImage;
- // Send the image to the user
- if (image.RawFormat.Guid == ImageFormat.Gif.Guid)
- {
- // Save the gif (but we can't ajust it's size or DPI, sorry)
- sizedImage = image.AdjustGifImage(maxWidth, maxHeight);
- }
- else
- {
- // Ajust and save image
- sizedImage = image.AdjustImage(maxWidth, maxHeight, -1);
- }
- // Set expiration and ETag
- HttpCachePolicyBase cache = HttpContext.Response.Cache;
- TimeSpan expireTs = TimeSpan.FromDays(7);
- cache.SetCacheability(HttpCacheability.Private);
- cache.SetETag(Language.Name + "_" + name + "_" + maxWidth + "_" + maxHeight);
- cache.SetExpires(DateTime.Now.Add(expireTs));
- cache.SetMaxAge(expireTs);
- // Check area
- if (sizedImage.Width * sizedImage.Height > maxOriginalArea)
- {
- Stream sizedImageStream = new MemoryStream();
- sizedImage.Save(sizedImageStream, ImageFormat.Png);
- sizedImageStream.Seek(0, SeekOrigin.Begin);
- FREE_IMAGE_FORMAT fiFormat = FREE_IMAGE_FORMAT.FIF_PNG;
- // Save to progressive jpeg
- FIBITMAP dib = new FIBITMAP();
- if (!dib.IsNull)
- FreeImage.Unload(dib);
- try
- {
- dib = FreeImage.LoadFromStream(sizedImageStream, FREE_IMAGE_LOAD_FLAGS.PNG_IGNOREGAMMA, ref fiFormat);
- }
- catch (BadImageFormatException exx)
- {
- throw new Exception("?????????! :( " + fiFormat.ToString(), exx);
- }
- if (!dib.IsNull)
- {
- Stream progressiveStream = new MemoryStream();
- if (FreeImage.SaveToStream(dib, progressiveStream, FREE_IMAGE_FORMAT.FIF_JPEG, FREE_IMAGE_SAVE_FLAGS.JPEG_PROGRESSIVE | FREE_IMAGE_SAVE_FLAGS.JPEG_QUALITYSUPERB))
- {
- // The bitmap was saved to stream but is still allocated in memory, so the handle has to be freed.
- if (!dib.IsNull)
- FreeImage.Unload(dib);
- // Make sure to set the handle to null so that it is clear that the handle is not pointing to a bitmap.
- dib.SetNull();
- progressiveStream.Seek(0, SeekOrigin.Begin);
- return File(progressiveStream, "image/jpeg", name);
- }
- }
- }
- // ELSE
- // Return image as png or jpeg
- if (image.RawFormat.Guid == ImageFormat.Gif.Guid
- || image.RawFormat.Guid == ImageFormat.Png.Guid)
- {
- byte[] bytes = sizedImage.SaveImage(ImageFormat.Png, outputImageQuality);
- return File(bytes, "image/png", name);
- }
- else
- {
- byte[] bytes = sizedImage.SaveImage(System.Drawing.Imaging.ImageFormat.Jpeg, outputImageQuality);
- return File(bytes, "image/jpeg", name);
- }
- }
- /// <summary>
- /// Returns <see cref="MessageResult"/> which renders view "Message".
- /// ViewData "Message" parameter is set.
- /// </summary>
- /// <param name="message">Message to show.</param>
- /// <param name="links">Additional links to show to user.</param>
- /// <returns>ViewResult which renders view "Message".</returns>
- protected virtual MessageResult Message(string message, params Link[] links)
- {
- return new MessageResult(message, links)
- {
- ViewData = this.ViewData,
- TempData = this.TempData
- };
- }
- /// <summary>
- /// Returns <see cref="MessageResult"/> which renders view "Message".
- /// ViewData "Message" parameter is set.
- /// </summary>
- /// <param name="message">Message to show.</param>
- /// <param name="autoRedirectUrl">Auto redirect url. If <c>Null</c> then auto redirect is disabled.</param>
- /// <param name="links">Additional links to show to user.</param>
- /// <returns>ViewResult which renders view "Message".</returns>
- protected virtual MessageResult Message(string message, string autoRedirectUrl, params Link[] links)
- {
- return new MessageResult(message, links)
- {
- ViewData = this.ViewData,
- TempData = this.TempData,
- AutoRedirectUrl = autoRedirectUrl
- };
- }
- /// <summary>
- /// Returns <see cref="HttpStatusCodeResult"/> with status code 401 if unauthorized and 403 if authorized.
- /// </summary>
- /// <param name="statusDescription">The status description.</param>
- protected virtual HttpStatusCodeResult HttpAccessDenied(string statusDescription = null)
- {
- int code = User == null ? 401 : 403;
- return new HttpStatusCodeResult(code, statusDescription);
- }
- /// <summary>
- /// Returns RedirectResult which redirects to referrer uri.
- /// </summary>
- /// <param name="defaultUrl">Default url to redirect to if referer is null.</param>
- protected RedirectResult RedirectToReferrer(string defaultUrl = "/")
- {
- Uri uri = Request.UrlReferrer;
- return Redirect(uri == null ? defaultUrl : uri.ToString());
- }
- /// <summary>
- /// Returns RedirectResult which redirects to ReturnUrl from request.
- /// If one is null then returns default url redirect.
- /// </summary>
- /// <param name="defaultUrl">Default url to redirect to if referer is null.</param>
- protected virtual RedirectResult RedirectToReturnUrl(string defaultUrl)
- {
- string returnUrl = ViewData["returnUrl"] as string;
- if (String.IsNullOrEmpty(returnUrl))
- returnUrl = Request["returnUrl"];
- if (String.IsNullOrEmpty(returnUrl))
- returnUrl = defaultUrl;
- return Redirect(returnUrl);
- }
- #endregion
- }
- }