MVC ViewPathProvider, database views and Layout - asp.net-mvc

I am trying to create a CMS using the MVC framework.
All was going well, I created my tables to store my ViewData, ViewTitle and virtualPath.
I use VirthPathProvider and it looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Hosting;
using CMS;
using System.Collections.ObjectModel;
using CMS.Components;
using System.Web;
namespace CMS.Providers
{
public class PageVirtualPathProvider : VirtualPathProvider
{
private Directory current { get; set; }
private Collection<Directory> directories { get; set; }
private Collection<BasePage> pages { get; set; }
public override bool FileExists(string virtualPath)
{
string Path = (VirtualPathUtility.GetDirectory(virtualPath) != "~/") ? VirtualPathUtility.RemoveTrailingSlash(VirtualPathUtility.GetDirectory(virtualPath)) : VirtualPathUtility.GetDirectory(virtualPath);
if (IsVirtualPath(Path))
{
BasePage oPage = FindPage(virtualPath);
if (oPage != null)
return true;
}
bool bExists = base.FileExists(virtualPath);
return bExists;
}
public override VirtualFile GetFile(string virtualPath)
{
string Path = (VirtualPathUtility.GetDirectory(virtualPath) != "~/") ? VirtualPathUtility.RemoveTrailingSlash(VirtualPathUtility.GetDirectory(virtualPath)) : VirtualPathUtility.GetDirectory(virtualPath);
if (IsVirtualPath(Path))
{
BasePage oPage = FindPage(virtualPath);
if (oPage != null)
return new PageVirtualFile(virtualPath, oPage.ViewData.ToArray());
}
return base.GetFile(virtualPath);
}
public override bool DirectoryExists(string virtualDir)
{
if (IsVirtualPath(virtualDir))
{
if (current != null)
{
if (current.Path.ToLower() != virtualDir.ToLower())
current = new Directory(virtualDir, "53AF0033-4011-4C8F-A14D-7CE9301E264D");
}
else
{
current = new Directory(virtualDir, "53AF0033-4011-4C8F-A14D-7CE9301E264D");
}
if (current != null)
return true;
}
return base.DirectoryExists(virtualDir);
}
public override VirtualDirectory GetDirectory(string virtualDir)
{
if (IsVirtualPath(virtualDir))
{
if (current != null)
{
if (current.Path.ToLower() != virtualDir.ToLower())
current = new Directory(virtualDir, "53AF0033-4011-4C8F-A14D-7CE9301E264D");
}
else
{
current = new Directory(virtualDir, "53AF0033-4011-4C8F-A14D-7CE9301E264D");
}
if (current != null)
return new CmsVirtualDirectory(virtualDir, "53AF0033-4011-4C8F-A14D-7CE9301E264D");
}
return base.GetDirectory(virtualDir);
}
public override System.Web.Caching.CacheDependency GetCacheDependency(string virtualPath, System.Collections.IEnumerable virtualPathDependencies, DateTime utcStart)
{
string Path = (VirtualPathUtility.GetDirectory(virtualPath) != "~/") ? VirtualPathUtility.RemoveTrailingSlash(VirtualPathUtility.GetDirectory(virtualPath)) : VirtualPathUtility.GetDirectory(virtualPath);
if (IsVirtualPath(Path))
return null;
return base.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
}
public override string GetFileHash(string virtualPath, System.Collections.IEnumerable virtualPathDependencies)
{
string Path = (VirtualPathUtility.GetDirectory(virtualPath) != "~/") ? VirtualPathUtility.RemoveTrailingSlash(VirtualPathUtility.GetDirectory(virtualPath)) : VirtualPathUtility.GetDirectory(virtualPath);
if (IsVirtualPath(Path))
return Guid.NewGuid().ToString();
return base.GetFileHash(virtualPath, virtualPathDependencies);
}
private BasePage FindPage(string virtualPath)
{
string VirtualName = VirtualPathUtility.GetFileName(virtualPath).ToLower();
if (pages == null)
{
pages = PageManager.getAllPages("53AF0033-4011-4C8F-A14D-7CE9301E264D", false);
}
BasePage oPage = pages.SingleOrDefault(page => page.Path.ToLower() == VirtualName);
return oPage;
}
private bool IsVirtualPath(string virtualPath)
{
string Path = VirtualPathUtility.ToAppRelative(virtualPath);
if (directories == null)
{
directories = DirectoryManager.GetAllDirectories("53AF0033-4011-4C8F-A14D-7CE9301E264D");
}
Directory oDir = directories.SingleOrDefault(dir => dir.Path.ToLower() == Path.ToLower());
if (oDir == null || virtualPath == "~/") return false; // If we don't have directory, return false
return true; // Hit only if we are null
}
}
}
Now my problem is this:
Getting the pages is fine, when they are virtual it returns null as Cache and the FileHash is always a different string, so GetFile is called.
My file is returned, but it never finds the Layout.
I believe this is because there is no _ViewStart.cshtml because there is no views directory....So how can I force it to use a Layout?
I have tried so many things, like getting my virtual pages to inherit from #inherits System.Web.Mvc.WebViewPage, etc, but I still get the same problem....
When I navigate to a virtual page, I get this error:
Unable to cast object of type 'ASP._Page_Guidelines_index_cshtml' to type 'System.Web.IHttpHandler'.
Please help me; I have been stuck on this for 3 weeks....

If anyone else is having this issue. I did solve it. Here is my complete code :)
First, create our RouteHandler
public class CmsRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return new CmsHandler(requestContext); // Return the requestContext and handle as normal
}
}
Then we need to create our MvcHanlder
class CmsHandler : MvcHandler, IRequiresSessionState
{
public CmsHandler(RequestContext requestContext)
: base(requestContext)
{
}
protected override IAsyncResult BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, object state)
{
return base.BeginProcessRequest(httpContext, callback, state);
}
protected override IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state)
{
try
{
// If we are using a company Url, then the session should not be null
if (CompanyProvider.CurrentCompanyId() != null)
{
var vpp = new CmsVirtualPathProvider(); // Create an instance of our VirtualPathProvider class
var requestContext = ((MvcHandler)httpContext.Handler).RequestContext; // Get our request context
string path = requestContext.HttpContext.Request.Url.AbsolutePath; // Get our requested path
// If we have a path
if (path != null)
{
Collection<IPage> pages = vpp.pages; // Get all the published pages for this company
// If we have pages
if (pages != null)
{
IPage oPage = pages.SingleOrDefault(page => page.Path.ToLower() == path.ToLower()); // Select the page matching our requested path (if any)
if (oPage != null) // If we find the page
{
requestContext.RouteData.Values["controller"] = "_Cms"; // Set the controller
requestContext.RouteData.Values["action"] = "Index"; // And the action
}
}
}
}
return base.BeginProcessRequest(httpContext, callback, state);
}
catch (Exception ex)
{
log4net.ILog _log = log4net.LogManager.GetLogger(this.GetType());
_log.Fatal(ex);
throw new Exception(ex.Message);
}
}
protected override void ProcessRequest(HttpContext httpContext)
{
base.ProcessRequest(httpContext);
}
}
You can see in my application I have a companyId that is because I am using subdomains for multiple companies, but in a normal case that would not be needed.
And the full VirtualPathProvider looks like this:
public class CmsVirtualPathProvider : VirtualPathProvider
{
public Collection<IPage> pages
{
get
{
if (HttpContext.Current.Session != null)
{
return PageProvider.GetPublishedPages(CompanyProvider.CurrentCompanyId(), true);
}
else
return null;
}
}
public override bool FileExists(string virtualPath)
{
if (IsVirtualPath(virtualPath))
{
if (FindPage(virtualPath) != null)
{
PageVirtualFile file = (PageVirtualFile)GetFile(virtualPath);
return file.Exists;
}
}
return Previous.FileExists(virtualPath);
}
public override VirtualFile GetFile(string virtualPath)
{
if (IsVirtualPath(virtualPath))
{
IPage oPage = FindPage(virtualPath);
if (oPage != null)
return new PageVirtualFile(virtualPath, oPage.ViewData);
}
return Previous.GetFile(virtualPath);
}
public override System.Web.Caching.CacheDependency GetCacheDependency(string virtualPath, System.Collections.IEnumerable virtualPathDependencies, DateTime utcStart)
{
if (IsVirtualPath(virtualPath))
return null;
return Previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
}
public override string GetFileHash(string virtualPath, System.Collections.IEnumerable virtualPathDependencies)
{
if (IsVirtualPath(virtualPath))
return Guid.NewGuid().ToString();
return Previous.GetFileHash(virtualPath, virtualPathDependencies);
}
private IPage FindPage(string virtualPath)
{
string VirtualName = VirtualPathUtility.GetFileName(virtualPath).ToLower();
if (pages != null)
{
IPage oPage = pages.SingleOrDefault(page => page.FileName == VirtualName);
return oPage;
}
else
return null;
}
private bool IsVirtualPath(string virtualPath)
{
string Path = (VirtualPathUtility.GetDirectory(virtualPath) != "~/") ? VirtualPathUtility.RemoveTrailingSlash(VirtualPathUtility.GetDirectory(virtualPath)) : VirtualPathUtility.GetDirectory(virtualPath);
if (Path.StartsWith("/Views/_Cms", StringComparison.InvariantCultureIgnoreCase))
return true;
else
return false;
}
}
Now you just need a controller to handle all the page requests. Mine looks like this:
public class _CmsController : Controller
{
private Collection<IPage> pages { get; set; }
public ActionResult Index()
{
string uri = Request.Url.AbsolutePath; // Get our Requested Url
string queryString = Request.Url.Query;
Profile currentUser = ProfileProvider.CurrentUser(); // Get our current user if we have one
if (pages == null) // If pages is null
pages = PageProvider.GetPublishedPages(CompanyProvider.CurrentCompanyId(), true); // Get our published pages
IPage page = pages.SingleOrDefault(p => p.Path.ToLower() == uri.ToLower()); // Get the current page
if (page == null) // If our page is null
throw new HttpException(404, "Are you sure this page exists?"); // Throw the 404 error
if (page.Restricted && currentUser == null) // If our page is restricted and we are not logged in
return Redirect("~/Account/LogOn?ReturnUrl=" + page.Path + queryString); // Redirect to the login page
if (currentUser != null)
{
IPage oForbidden = currentUser.GetForbiddenPages().SingleOrDefault(p => p.Id == page.Id); // Finds the page in our forbidden pages, if it exists
if (oForbidden != null) // If we find the forbidden page
throw new HttpException(401, "You do not have permission to view this page."); // Throw 401 error
AuditProvider.Create(currentUser, page, Event.View); // Create our audit trail if we get this far
}
return View(Path.GetFileNameWithoutExtension(page.Id.ToString())); // Show the page
}
}
And just because I am feeling nice, here is my table structure
CREATE TABLE [dbo].[cms_Pages](
[Id] [int] IDENTITY(1,1) NOT NULL,
[DateCreated] [datetime] NOT NULL,
[UserId] [uniqueidentifier] NOT NULL,
[Author] [nvarchar](256) NOT NULL,
[DateModified] [datetime] NULL,
[ModifiedById] [uniqueidentifier] NULL,
[ModifiedBy] [nvarchar](256) NULL,
[CompanyId] [uniqueidentifier] NOT NULL,
[Name] [varchar](100) NOT NULL,
[Description] [text] NULL,
[FileName] [varchar](255) NULL,
[Path] [varchar](255) NULL,
[Link] [varchar](255) NULL,
[Published] [bit] NOT NULL,
[TypeId] [int] NOT NULL,
[Order] [int] NOT NULL,
[Lineage] [nvarchar](255) NOT NULL,
[ParentId] [int] NULL,
[ViewData] [varbinary](max) NULL,
[ViewTitle] [varchar](255) NULL,
[Restricted] [bit] NOT NULL,
CONSTRAINT [PK_cg_Pages] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
obviously again, you don't need the companyId :)
Here is a peek at the data contained inside the table
I transformed the html for a page into bytes using this line of code:
ASCIIEncoding encoding = new ASCIIEncoding();
var decodedContent = HttpUtility.UrlDecode(Content, Encoding.Default);
Byte[] bytes = encoding.GetBytes(decodedContent);
you only need the UrlDecode if you are escaping your HTML before submitting it to your save function. If you are not then you can just use:
ASCIIEncoding encoding = new ASCIIEncoding();
Byte[] bytes = encoding.GetBytes(Content);
I really hope this helps someone out. I was in a right mess trying to work this out :)
cheers,
r3plica

Related

How to create a unique session for a user: ASP.NET

I have been learning ASP.NET and came to point where I realised that my web application is creating only a static session for all the users, that is if one logs out all the users are logged out, and sometimes the session is even swapped (lets say userA logs in and right after userB logs in, when the userA refreshes he is seeing the data of userB).
My SessionManager class is as below
SessionManager.cs
public class SessionManager
{
#region Private Data
private static String USER_KEY = "user";
#endregion
public static Employee CurrentUser
{
get;
set;
}
public static string UserType
{
get;
set;
}
public static Int32 SessionTimeout
{
get
{
return System.Web.HttpContext.Current.Session.Timeout;
}
}
public static String GetUserFullName()
{
if (SessionManager.CurrentUser != null)
return SessionManager.CurrentUser.FirstName;
else
return null;
}
public static Boolean IsUserLoggedIn
{
get
{
if (SessionManager.CurrentUser != null)
return true;
else
return false;
}
}
#region Methods
public static void AbandonSession()
{
for (int i = 0; i < System.Web.HttpContext.Current.Session.Count; i++)
{
System.Web.HttpContext.Current.Session[i] = null;
}
System.Web.HttpContext.Current.Session.Abandon();
}
#endregion
}
Login Controller:
[HttpPost]
public ActionResult Index(String txtUserName, String txtPassword)
if (User.Identity.IsAuthenticated)
{
return View();
}
else
{
if (ModelState.IsValid)
{
Employee obj = (from o in db.Employees
where o.Email == txtUserName && o.Password == txtPassword
select o).FirstOrDefault();
if (obj != null)
{
var dh = db.Departments.Where(x => x.LeadBy == obj.EmployeeId).FirstOrDefault();
var tl = db.Teams.Where(x => x.LeadBy == obj.EmployeeId).FirstOrDefault();
if (dh == null && tl == null)
{
Session["UserType"] = "EMP";
}
else if (dh != null && tl != null)
{
Session["UserType"] = "DH&TL";
}
else if (dh != null)
{
Session["UserType"] = "DH";
}
else if (tl != null)
{
Session["UserType"] = "TL";
}
SessionManager.CurrentUser = obj; //how can I create different obj for different users here?
var currentEnrollID = SessionManager.CurrentUser.EnrollNumber;
var currentEmployeeID = SessionManager.CurrentUser.EmployeeId;
var currentEmpName = SessionManager.CurrentUser.FirstName + " " + SessionManager.CurrentUser.LastName;
I have been using sessions like this in the whole application so a different approach would be hectic to amend the changes.
public ActionResult Logout()
{
if (SessionManager.IsUserLoggedIn)
{
SessionManager.CurrentUser.EmployeeId = 0;
SessionManager.AbandonSession();
Session.Clear();
Session.Abandon();
Session.RemoveAll();
}
return RedirectToAction("Index","Login");
}
This is not related to ASP.NET, but it is more on how static members work.
The real issue is your SessionsManager, which contains static methods that you store values every time the user logs-in. This means the same instance is shared across different session in the application.
I have an update SessionManager you can see below. I have stored the SessionManager object in the session object so that as long the session is alive. It will return the same instance by session when you call it using SessionManager.Current.
public class SessionManager {
#region Private Data
private static String USER_KEY = "user";
#endregion
public static SessionManager Current {
get{
if (HttpContext.Current.Session[USER_KEY] != null) {
return (SessionManager) HttpContext.Current.Session[USER_KEY];
} else {
var sess = new SessionManager ();
HttpContext.Current.Session[USER_KEY] = sess;
return sess;
}
}
}
public Employee CurrentUser {
get;
set;
}
public string UserType {
get;
set;
}
public Int32 SessionTimeout {
get {
return System.Web.HttpContext.Current.Session.Timeout;
}
}
public String GetUserFullName () {
if (SessionManager.Current.CurrentUser != null)
return SessionManager.Current.CurrentUser.FirstName;
else
return null;
}
public Boolean IsUserLoggedIn {
get {
if (SessionManager.Current.CurrentUser != null)
return true;
else
return false;
}
}
#region Methods
public void AbandonSession () {
for (int i = 0; i < System.Web.HttpContext.Current.Session.Count; i++) {
System.Web.HttpContext.Current.Session[i] = null;
}
System.Web.HttpContext.Current.Session.Abandon ();
}
#endregion
}

ASP NET MVC VirtualPathProvider avoid some paths

I wrote a VirtualPathProvider to dynamically load my MVC views, which are saved in a database. The problem is that it is taking too long to load the views because the class ViewPathProvider is getting all paths and searching for them in the database:
"/PrecompiledApp.config",
"~/_appstart.cshtml",
"~/_appstart.vbhtml"
"/Views/Home/Index.aspx",
"/Views/Home/Index.ascx",
"/Views/Shared/Index.aspx"
(...) and many others. Is there a way to define a list of paths to reduce time and the number of queries made against the db?
My Global.asax.cs
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
HostingEnvironment.RegisterVirtualPathProvider(new ViewPathProvider());
}
My VirtualPathProvider.cs
public class ViewPathProvider : VirtualPathProvider
{
public override bool FileExists(string virtualPath)
{
var page = FindPage(virtualPath);
if (page == null)
{
return base.FileExists(virtualPath);
}
else
{
return true;
}
}
public override VirtualFile GetFile(string virtualPath)
{
var page = FindPage(virtualPath);
if (page == null)
{
return base.GetFile(virtualPath);
}
else
{
return new MyVirtualFile(virtualPath, page);
}
}
public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart)
{
return null;
}
public override string GetFileHash(string virtualPath, IEnumerable virtualPathDependencies)
{
return Guid.NewGuid().ToString();
}
private string FindPage(string virtualPath)
{
string filetype = virtualPath.Substring(virtualPath.Length - 5);
if(filetype != ".aspx" && filetype != ".ascx" && filetype != "bhtml")
{
Uri host = System.Web.HttpContext.Current.Request.Url;
string hostName = host.Host.ToString();
Company company = new Company();
CMSComponent companiesComponent = new CMSComponent();
company = companiesComponent.GetCompanyDetailsByCmsUrl(hostName, virtualPath);
Debug.Print(virtualPath);
if (company.CompanyId!=0)
{
return company.cmsHtml;
}
else
{
return null;
}
}
else
{
return null;
}
}
}
Thanks!

Using MVCMailer to embed image from MemoryStream in email

I use MVCMailer with asp.net MVC 3.
It's a great library but I have a problem.
I saw it's possible to embed image in email like so :
var resources = new Dictionary<string, string>();
resources["image"] = imagePath;
PopulateBody(mailMessage, "WelcomeMessage", resources);
Therefore it looks like "resources" is expecting a path to the image from the filesystem, however, my image is in memorystream.
Would it be possible to embed the image as a base64 straight away without having to actually write the file on disk and then pass the path?
Thanks for your help!
Baucause MVCMailer is based on System.Net.Mail it's easy to add LinkedResource as stream.
Here is the fix :
in ILinkedResourceProvider.cs add :
List<LinkedResource> GetAll(Dictionary<string, MemoryStream> resources);
LinkedResource Get(string contentId, MemoryStream stream);
in LinkedResourceProvider add :
public virtual List<LinkedResource> GetAll(Dictionary<string, MemoryStream> resources)
{
var linkedResources = new List<LinkedResource>();
foreach (var resource in resources)
{
linkedResources.Add(Get(resource.Key, resource.Value));
}
return linkedResources;
}
public virtual LinkedResource Get(string contentId, MemoryStream stream)
{
LinkedResource resource = new LinkedResource(stream);
resource.ContentId = contentId;
return resource;
}
In MailerBase.cs add :
public virtual void PopulateBody(MailMessage mailMessage, string viewName, Dictionary<string, MemoryStream> linkedResources)
{
PopulateBody(mailMessage, viewName, null, linkedResources);
}
public virtual void PopulateBody(MailMessage mailMessage, string viewName, string masterName = null, Dictionary<string, MemoryStream> linkedResources = null)
{
if (mailMessage == null)
{
throw new ArgumentNullException("mailMessage", "mailMessage cannot be null");
}
masterName = masterName ?? MasterName;
var linkedResourcesPresent = linkedResources != null && linkedResources.Count > 0;
var textExists = TextViewExists(viewName, masterName);
//if Text exists, it always goes to the body
if (textExists)
{
PopulateTextBody(mailMessage, viewName, masterName);
}
// if html exists
if (HtmlViewExists(viewName, masterName))
{
if (textExists || linkedResourcesPresent)
{
PopulateHtmlPart(mailMessage, viewName, masterName, linkedResources);
}
else
{
PopulateHtmlBody(mailMessage, viewName, masterName);
}
}
}
public virtual AlternateView PopulateHtmlPart(MailMessage mailMessage, string viewName, string masterName, Dictionary<string, MemoryStream> linkedResources)
{
var htmlPart = PopulatePart(mailMessage, viewName, "text/html", masterName);
if (htmlPart != null)
{
PopulateLinkedResources(htmlPart, linkedResources);
}
return htmlPart;
}
public virtual List<LinkedResource> PopulateLinkedResources(AlternateView mailPart, Dictionary<string, MemoryStream> resources)
{
if (resources == null || resources.Count == 0)
return new List<LinkedResource>();
var linkedResources = LinkedResourceProvider.GetAll(resources);
linkedResources.ForEach(resource => mailPart.LinkedResources.Add(resource));
return linkedResources;
}
Hope it will be part of next MVCMailer release.

ASP.NET MVC 3 inheriting Membership userId

I am looking to extend the aspnet_membership in an MVC 3 application by storing extra member details in a separate model/table. I am not looking at using the ASP.NET ProfileProvider.
I would like to use the userId of a member as the primary/foreign key in the additional model/table. How can I achieve this? Is the example code along the right lines?
Thanks for any help.
public class Profile
{
[Key]
public Guid ProfileId { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public virtual MembershipUser User
{
get { return Membership.GetUser(ProfileId); }
}
public string FullName
{
get { return LastName + ", " + FirstName; }
}
}
That's what I do in my project, I have an other class wich is Member and inside I have the Email. I have a AuthenticationService that I use to sing in my user here's the code of this AuthenticationService...
In the web.config I have two differents connection string, one for the application BD and the other for the membership BD.
public class AuthenticationService : IAuthenticationService
{
private readonly IConfigHelper _configHelper;
private readonly ISession _session;
public AuthenticationService(IConfigHelper configHelper, ISession session)
{
_configHelper = configHelper;
_session = session;
}
public bool IsValidLogin(string email, string password)
{
CheckLocked(email);
return Membership.ValidateUser(email, password);
}
public void SignIn(string email, bool createPersistentCookie)
{
if (String.IsNullOrEmpty(email)) throw new ArgumentException("Value cannot be null or empty.", "email");
FormsAuthentication.SetAuthCookie(email, createPersistentCookie);
}
public void SignOut()
{
FormsAuthentication.SignOut();
}
public User GetLoggedUser()
{
var email = GetLoggedInUserName();
if (IsMember())
return _session.Single<Member>(x => x.Email == email);
return _session.Single<DelegateMember>(x => x.Email == email);
}
public string GetLoggedInUserName()
{
return Membership.GetUser() != null ? Membership.GetUser().UserName : string.Empty;
}
public MembershipCreateStatus RegisterUser(string email, string password, string role)
{
MembershipCreateStatus status;
//On doit laisser Guid.NewGuid().ToString() sinon ça ne passe pas
Membership.CreateUser(email, password, email, Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), true, out status);
if (status == MembershipCreateStatus.Success)
{
Roles.AddUserToRole(email, role);
}
return status;
}
public MembershipUserCollection GetAllUsers()
{
return Membership.GetAllUsers();
}
public string GeneratePassword()
{
var alphaCaps = "QWERTYUIOPASDFGHJKLZXCVBNM";
var alphaLow = "qwertyuiopasdfghjklzxcvbnm";
var numerics = "1234567890";
var special = "##$";
var allChars = alphaCaps + alphaLow + numerics + special;
var r = new Random();
var generatedPassword = "";
for (int i = 0; i < MinPasswordLength - 1; i++)
{
double rand = r.NextDouble();
if (i == 0)
{
//First character is an upper case alphabet
generatedPassword += alphaCaps.ToCharArray()[(int)Math.Floor(rand * alphaCaps.Length)];
//Next one is numeric
rand = r.NextDouble();
generatedPassword += numerics.ToCharArray()[(int) Math.Floor(rand*numerics.Length)];
}
else
{
generatedPassword += allChars.ToCharArray()[(int)Math.Floor(rand * allChars.Length)];
}
}
return generatedPassword;
}
public int MinPasswordLength
{
get
{
return Membership.Provider.MinRequiredPasswordLength;
}
}
public string AdminRole
{
get { return "admin"; }
}
public string MemberRole
{
get { return "member"; }
}
public string DelegateRole
{
get { return "delegate"; }
}
public string AgentRole
{
get { return "agent"; }
}
public bool Delete(string email)
{
return Membership.DeleteUser(email);
}
public bool IsAdmin()
{
return Roles.IsUserInRole(AdminRole);
}
public bool IsMember()
{
return Roles.IsUserInRole(MemberRole);
}
public bool IsDelegate()
{
return Roles.IsUserInRole(DelegateRole);
}
public bool IsAgent()
{
return Roles.IsUserInRole(AgentRole);
}
public bool ChangePassword(string email, string oldPassword, string newPassword)
{
if (String.IsNullOrEmpty(email)) throw new ArgumentException("Value cannot be null or empty.", "email");
if (String.IsNullOrEmpty(oldPassword)) throw new ArgumentException("Value cannot be null or empty.", "oldPassword");
if (String.IsNullOrEmpty(newPassword)) throw new ArgumentException("Value cannot be null or empty.", "newPassword");
// The underlying ChangePassword() will throw an exception rather
// than return false in certain failure scenarios.
try
{
var currentUser = Membership.Provider.GetUser(email, true);
return currentUser.ChangePassword(oldPassword, newPassword);
}
catch (ArgumentException)
{
return false;
}
catch (MembershipPasswordException)
{
return false;
}
}
public string ResetPassword(string email)
{
if (String.IsNullOrEmpty(email)) throw new ArgumentException("Value cannot be null or empty.", "email");
Unlock(email);
var currentUser = Membership.Provider.GetUser(email, false);
return currentUser.ResetPassword();
}
public bool CheckLocked(string email)
{
if (String.IsNullOrEmpty(email)) throw new ArgumentException("Value cannot be null or empty.", "email");
var currentUser = Membership.Provider.GetUser(email, false);
if (currentUser == null) return false;
if (!currentUser.IsLockedOut) return false;
if (currentUser.LastLockoutDate.AddMinutes(30) < DateTime.Now)
{
currentUser.UnlockUser();
return false;
}
return true;
}
public bool Unlock(string email)
{
if (String.IsNullOrEmpty(email)) throw new ArgumentException("Value cannot be null or empty.", "email");
var currentUser = Membership.Provider.GetUser(email, false);
if (currentUser == null) return false;
currentUser.UnlockUser();
return true;
}
}
I hope it can help!

Session is null in HttpHandler but not in MVC Controller

I have security in my MVC application set up with an authorize attribute...
public class UserLoggedInAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Session["UserId"] == null)
{
var values = new { controller = "Home", action = "Index" };
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(values));
}
}
}
Then I also have a .ashx HttpHandler which is called by jQuery upload control....
public class UploadFile : IHttpHandler, IReadOnlySessionState
{
...
private bool EnsureSecureTransaction(HttpContext context)
{
if (context.Session["UserId"] == null)
{
return false;
}
else
{
return true;
}
return true;
}
}
When EnsureSecureTransaction() gets called the session is coming back null. But session that is read in my MVC action its not. I notice that I'm taking session from the filterContext though.
I have tried to change all the code to try and reference HttpContext.Current.Session like this
[HttpPost]
public ActionResult Logon(AdminModel model)
{
if (model.UserName == "x" && model.Password == "x")
{
HttpContext.Session["UserId"] = "true";
return RedirectToAction("CreateBlog", "Blog");
}
return View;
}
private bool EnsureSecureTransaction(HttpContext context)
{
if (context.Session["UserId"] == null)
{
return false;
}
else
{
return true;
}
return true;
}
But basically when I hit the EnsureSecureTransaction() block its still saying my Session["UserId"] is null and therefor not autehenticating the call to the .ashx file correctly.
Anyone know why this is? Whats the actual difference between AuthorizationContext and HttpContext with regards to the session they carry and how do I get round this problem?

Resources