Just a quick tip, I recently had a click event on an anchor tag and a get that loaded in some content when clicked like so:
$('#myid').click(function() {
$.get('mvcurlhere', function (data) {
//load my div here
})
});
if you find yourself scratching your head when your MVC call using ajax and $.get seems not to be returning its because you didn't stop the original anchor from calling back, once more if your anchor tag has a # as the href which we all do from time to time, you will get the same page back with a # appended to the url and all sorts of great stuff starts happening my friends (especially with Chrome)
Solution ? remember the JQuery event.preventDefault call :
$('#myid').click(function(event) {
event.preventDefault();
$.get('mvcurlhere', function (data) {
//load my div here
})
});
Happy days.....
All sorts of stuff i have found along the way contracting that may be of use to others... who knows ??
Thursday, 4 July 2013
Thursday, 16 May 2013
Example of mocking a job execution context in Quartz.net and Moq
I wanted to mock the IJobExecution context for my Quartz job today and wanted to use some of the job parameters, there is a little bit to setup, so here's an example of a starting point:
The Trigger
This is simple enough, create an object that implements ITrigger, I called mine "FakeTrigger", here i've only impelmented the StartTimeUTC
public class FakeTrigger : ITrigger
{
public object Clone()
{
throw new NotImplementedException();
}
public int CompareTo(ITrigger other)
{
throw new NotImplementedException();
}
public IScheduleBuilder GetScheduleBuilder()
{
throw new NotImplementedException();
}
public bool GetMayFireAgain()
{
throw new NotImplementedException();
}
public DateTimeOffset? GetNextFireTimeUtc()
{
throw new NotImplementedException();
}
public DateTimeOffset? GetPreviousFireTimeUtc()
{
throw new NotImplementedException();
}
public DateTimeOffset? GetFireTimeAfter(DateTimeOffset? afterTime)
{
throw new NotImplementedException();
}
public TriggerKey Key
{
get { throw new NotImplementedException(); }
}
public JobKey JobKey
{
get { throw new NotImplementedException(); }
}
public string Description
{
get { throw new NotImplementedException(); }
}
public string CalendarName
{
get { throw new NotImplementedException(); }
}
public JobDataMap JobDataMap
{
get { throw new NotImplementedException(); }
}
public DateTimeOffset? FinalFireTimeUtc
{
get { throw new NotImplementedException(); }
}
public int MisfireInstruction
{
get { throw new NotImplementedException(); }
}
public DateTimeOffset? EndTimeUtc
{
get { throw new NotImplementedException(); }
}
public DateTimeOffset StartTimeUtc
{
get { return new DateTimeOffset(DateTime.Now); }
}
public int Priority
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public bool HasMillisecondPrecision
{
get { throw new NotImplementedException(); }
}
}
Creating the context
This is simply a Moq IJobExecutioncontext
_mockJobExecutionContext = new Mock<IJobExecutionContext>();
Creating the Job Detail
A bit more unknown is the JobDetail object, but this is a new JobDetailImpl object :
_jobdetail = new JobDetailImpl("jobsettings", typeof (IJob));
We can then set up the get of this using Moq:
_mockJobExecutionContext = new Mock<IJobExecutionContext>();
_mockJobExecutionContext.SetupGet(p => p.JobDetail).Returns(_jobdetail);
We can also set up the job details such as description and key etc.
_mockJobExecutionContext.SetupGet(p => p.JobDetail.Description).Returns("jobdescription");
_mockJobExecutionContext.SetupGet(p => p.JobDetail.Key).Returns(new JobKey("jobkey",
"jobkeyvalue"));
The Job Data Map
The job data map is the settings that get passed to the job, this is a JobDataMap object but is instanciated with a list of key value pairs :
IDictionary<string, object> keyValuePairs = new Dictionary<string, object>();
keyValuePairs.Add("fromAddress", "fromaddress@email.org");
keyValuePairs.Add("toaddress", "toaddress@email.org");
JobDataMap jobDataMap = new JobDataMap(keyValuePairs);
We can then set the get up of that :
_mockJobExecutionContext.SetupGet(p => p.JobDetail.JobDataMap).Returns(jobDataMap );
Wrapping up
Finally set up the remining bits such as the trigger
_mockJobExecutionContext.SetupGet(p => p.Trigger).Returns(_trigger);
Then we can test :
job.Execute(_mockJobExecutionContext.Object);
Hurah !
The Trigger
This is simple enough, create an object that implements ITrigger, I called mine "FakeTrigger", here i've only impelmented the StartTimeUTC
public class FakeTrigger : ITrigger
{
public object Clone()
{
throw new NotImplementedException();
}
public int CompareTo(ITrigger other)
{
throw new NotImplementedException();
}
public IScheduleBuilder GetScheduleBuilder()
{
throw new NotImplementedException();
}
public bool GetMayFireAgain()
{
throw new NotImplementedException();
}
public DateTimeOffset? GetNextFireTimeUtc()
{
throw new NotImplementedException();
}
public DateTimeOffset? GetPreviousFireTimeUtc()
{
throw new NotImplementedException();
}
public DateTimeOffset? GetFireTimeAfter(DateTimeOffset? afterTime)
{
throw new NotImplementedException();
}
public TriggerKey Key
{
get { throw new NotImplementedException(); }
}
public JobKey JobKey
{
get { throw new NotImplementedException(); }
}
public string Description
{
get { throw new NotImplementedException(); }
}
public string CalendarName
{
get { throw new NotImplementedException(); }
}
public JobDataMap JobDataMap
{
get { throw new NotImplementedException(); }
}
public DateTimeOffset? FinalFireTimeUtc
{
get { throw new NotImplementedException(); }
}
public int MisfireInstruction
{
get { throw new NotImplementedException(); }
}
public DateTimeOffset? EndTimeUtc
{
get { throw new NotImplementedException(); }
}
public DateTimeOffset StartTimeUtc
{
get { return new DateTimeOffset(DateTime.Now); }
}
public int Priority
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public bool HasMillisecondPrecision
{
get { throw new NotImplementedException(); }
}
}
Creating the context
This is simply a Moq IJobExecutioncontext
_mockJobExecutionContext = new Mock<IJobExecutionContext>();
Creating the Job Detail
A bit more unknown is the JobDetail object, but this is a new JobDetailImpl object :
_jobdetail = new JobDetailImpl("jobsettings", typeof (IJob));
We can then set up the get of this using Moq:
_mockJobExecutionContext = new Mock<IJobExecutionContext>();
_mockJobExecutionContext.SetupGet(p => p.JobDetail).Returns(_jobdetail);
We can also set up the job details such as description and key etc.
_mockJobExecutionContext.SetupGet(p => p.JobDetail.Description).Returns("jobdescription");
_mockJobExecutionContext.SetupGet(p => p.JobDetail.Key).Returns(new JobKey("jobkey",
"jobkeyvalue"));
The Job Data Map
The job data map is the settings that get passed to the job, this is a JobDataMap object but is instanciated with a list of key value pairs :
IDictionary<string, object> keyValuePairs = new Dictionary<string, object>();
keyValuePairs.Add("fromAddress", "fromaddress@email.org");
keyValuePairs.Add("toaddress", "toaddress@email.org");
JobDataMap jobDataMap = new JobDataMap(keyValuePairs);
We can then set the get up of that :
_mockJobExecutionContext.SetupGet(p => p.JobDetail.JobDataMap).Returns(jobDataMap );
Wrapping up
Finally set up the remining bits such as the trigger
_mockJobExecutionContext.SetupGet(p => p.Trigger).Returns(_trigger);
Then we can test :
job.Execute(_mockJobExecutionContext.Object);
Hurah !
Wednesday, 24 April 2013
Watin and Could not load file or assembly 'CassiniDev4-lib, Version=4.0.1.7 or one of its dependencies. An attempt was made to load a program with an incorrect format.
Just in case you get this little nugget like i did this morning when writing your tests, make sure you have the project set to X86.
A.
A.
Wednesday, 27 March 2013
debugger; the command i keep forgetting !
So i'm trying to debug ajax responses in a webpage so i go to my chrome browser dev tools, check the src code and nothing....
I keep forgetting to add :
debugger;
to the ajax response, if we do this, then chrome swings into action and we get our breakpoint so we can debug the response. Hepefully this will help anyone reading this in the future if they are as absent minded as myself.
A.
Wednesday, 23 January 2013
The EntitySet name 'X' from the object's EntityKey does not match the expected EntitySet name, 'Y'.
Go this one tonight, and caused me some grief for a bit.
Basically, I have a foreign key mapping to my company into my user profile and I was trying to perform an update on the foreign key. Here's my user profile:
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public string EmailAddress { get; set; }
public string Firstname { get; set; }
public string Surname { get; set; }
[ForeignKey("CompanyId")]
public Company Company { get; set; }
public int CompanyId { get; set; }
}
if you want to update the company you have to set the company to null but set the foreign key seperately :
using (var context = new UsersContext())
{
profile.UserName = userViewModel.UserName;
profile.EmailAddress = userViewModel.EmailAddress;
profile.Firstname = userViewModel.FirstName;
profile.Surname = userViewModel.Surname;
profile.Company = null;
profile.CompanyId = userViewModel.CompanyId;
//profile.Company = userViewModel.Companies.FirstOrDefault(c => c.Id == userViewModel.CompanyId);
context.Entry(profile).State = EntityState.Modified;
context.SaveChanges();
}
now it works !
Basically, I have a foreign key mapping to my company into my user profile and I was trying to perform an update on the foreign key. Here's my user profile:
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public string EmailAddress { get; set; }
public string Firstname { get; set; }
public string Surname { get; set; }
[ForeignKey("CompanyId")]
public Company Company { get; set; }
public int CompanyId { get; set; }
}
if you want to update the company you have to set the company to null but set the foreign key seperately :
using (var context = new UsersContext())
{
profile.UserName = userViewModel.UserName;
profile.EmailAddress = userViewModel.EmailAddress;
profile.Firstname = userViewModel.FirstName;
profile.Surname = userViewModel.Surname;
profile.Company = null;
profile.CompanyId = userViewModel.CompanyId;
//profile.Company = userViewModel.Companies.FirstOrDefault(c => c.Id == userViewModel.CompanyId);
context.Entry(profile).State = EntityState.Modified;
context.SaveChanges();
}
now it works !
Tuesday, 22 January 2013
Making your website fonts a touch better
Hi there,
So until all the browser vendors decide to implement font-smoothing in css (not holding out any hope), here's a little trick I learn't of and started using that makes the fonts look a touch better when in your website.
there are a couple of other techniques out there like cufon and phark which tbh seem a little bit like overkill for the sake of having your text look good. So whilst browsing round, I noticed an article that mentioned the text shadow effect and having a shadow that is between the backgound and your text colour will help smooth out those nasty jaggies....
I have tried the line
-webkit-font-smoothing: antialiased;
which doesn't seem to give me any kind of different result. Instead, lets use the shadow ,method here's a quick example:
font-size: 75%;
background-color: #f0f0f0;
text-shadow: 0 0 1px rgba(51, 51, 51, 0.5);
font-family: Helvetica, arial, freesans, clean, sans-serif;
I've set up the a text size and family (seems to look better on helvetica based fonts on the ones I have tried). then I have set a text shadow up with no offset but a slight blur (1px) and semi transparent grey (the rgba).
coming to set a heading up, I have set its colour to a darker grey too:
h1 { font-size: 1.8em; font-weight: normal; color: #666; padding: 0; margin: 0;}
The results are as below (before and after)
So until all the browser vendors decide to implement font-smoothing in css (not holding out any hope), here's a little trick I learn't of and started using that makes the fonts look a touch better when in your website.
there are a couple of other techniques out there like cufon and phark which tbh seem a little bit like overkill for the sake of having your text look good. So whilst browsing round, I noticed an article that mentioned the text shadow effect and having a shadow that is between the backgound and your text colour will help smooth out those nasty jaggies....
I have tried the line
-webkit-font-smoothing: antialiased;
which doesn't seem to give me any kind of different result. Instead, lets use the shadow ,method here's a quick example:
font-size: 75%;
background-color: #f0f0f0;
text-shadow: 0 0 1px rgba(51, 51, 51, 0.5);
font-family: Helvetica, arial, freesans, clean, sans-serif;
I've set up the a text size and family (seems to look better on helvetica based fonts on the ones I have tried). then I have set a text shadow up with no offset but a slight blur (1px) and semi transparent grey (the rgba).
coming to set a heading up, I have set its colour to a darker grey too:
h1 { font-size: 1.8em; font-weight: normal; color: #666; padding: 0; margin: 0;}
The results are as below (before and after)
Not perfect, but a great quick solution. i'm sure if you played more with the colours, you could get it a touch better.
A.
Saturday, 5 January 2013
Simple membership in MVC 4 quick setup guide
Hi folks,
Just working on a project at home and thought I would use the simple membership in mvc 4 as it's pretty neat. We have a database already created so i'm using it from a database first perspective and thought i'd share the findings here in case someone else needs to do this. Most of this can be gleaned from creating a blank internet application and getting the bits necessary but thought I would put it in one place for ease of use.
the usual way to go about simple membership is to create an internet application which will do all the gubbins for you and create these tables :
In the old membership we used to run the aspnet_regsql command to register the membership tables. if you need to tables in this example, fear not, the scripts are below. PLEASE NOTE I TAKE NO RESPONSIBILITY IF THEY DESTROY YOUR DB. these were just generated with create script on the tables.
/****** Object: Table [dbo].[UserProfile] Script Date: 01/05/2013 23:09:00 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[UserProfile](
[UserId] [int] IDENTITY(1,1) NOT NULL,
[UserName] [nvarchar](56) NOT NULL,
PRIMARY KEY CLUSTERED
(
[UserId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
UNIQUE NONCLUSTERED
(
[UserName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[webpages_Membership] Script Date: 01/05/2013 22:55:24 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[webpages_Membership](
[UserId] [int] NOT NULL,
[CreateDate] [datetime] NULL,
[ConfirmationToken] [nvarchar](128) NULL,
[IsConfirmed] [bit] NULL,
[LastPasswordFailureDate] [datetime] NULL,
[PasswordFailuresSinceLastSuccess] [int] NOT NULL,
[Password] [nvarchar](128) NOT NULL,
[PasswordChangedDate] [datetime] NULL,
[PasswordSalt] [nvarchar](128) NOT NULL,
[PasswordVerificationToken] [nvarchar](128) NULL,
[PasswordVerificationTokenExpirationDate] [datetime] NULL,
PRIMARY KEY CLUSTERED
(
[UserId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[webpages_Membership] ADD DEFAULT ((0)) FOR [IsConfirmed]
GO
ALTER TABLE [dbo].[webpages_Membership] ADD DEFAULT ((0)) FOR [PasswordFailuresSinceLastSuccess]
GO
/****** Object: Table [dbo].[webpages_Roles] Script Date: 01/05/2013 22:56:30 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[webpages_Roles](
[RoleId] [int] IDENTITY(1,1) NOT NULL,
[RoleName] [nvarchar](256) NOT NULL,
PRIMARY KEY CLUSTERED
(
[RoleId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
UNIQUE NONCLUSTERED
(
[RoleName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[webpages_OAuthMembership] Script Date: 01/05/2013 22:56:56 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[webpages_OAuthMembership](
[Provider] [nvarchar](30) NOT NULL,
[ProviderUserId] [nvarchar](100) NOT NULL,
[UserId] [int] NOT NULL,
PRIMARY KEY CLUSTERED
(
[Provider] ASC,
[ProviderUserId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[webpages_UsersInRoles] Script Date: 01/05/2013 22:57:21 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[webpages_UsersInRoles](
[UserId] [int] NOT NULL,
[RoleId] [int] NOT NULL,
PRIMARY KEY CLUSTERED
(
[UserId] ASC,
[RoleId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[webpages_UsersInRoles] WITH CHECK ADD CONSTRAINT [fk_RoleId] FOREIGN KEY([RoleId])
REFERENCES [dbo].[webpages_Roles] ([RoleId])
GO
ALTER TABLE [dbo].[webpages_UsersInRoles] CHECK CONSTRAINT [fk_RoleId]
GO
ALTER TABLE [dbo].[webpages_UsersInRoles] WITH CHECK ADD CONSTRAINT [fk_UserId] FOREIGN KEY([UserId])
REFERENCES [dbo].[UserProfile] ([UserId])
GO
ALTER TABLE [dbo].[webpages_UsersInRoles] CHECK CONSTRAINT [fk_UserId]
GO
With the tables created, add the following to the web.config :
<roleManager enabled="true" defaultProvider="SimpleRoleProvider">
<providers>
<clear/>
<add name="SimpleRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData"/>
</providers>
</roleManager>
<membership defaultProvider="SimpleMembershipProvider">
<providers>
<clear/>
<add name="SimpleMembershipProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
</providers>
</membership>
Which adds the standard providers for simple membership. The project includes a filter attribute which you can place at the top of any of your controllers that need to make use of membership, the default class is the InitializeSimpleMembershipAttribute and looks like this:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
{
private static SimpleMembershipInitializer _initializer;
private static object _initializerLock = new object();
private static bool _isInitialized;
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Ensure ASP.NET Simple Membership is initialized only once per app start
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}
private class SimpleMembershipInitializer
{
public SimpleMembershipInitializer()
{
Database.SetInitializer<UsersContext>(null);
try
{
using (var context = new UsersContext())
{
if (!context.Database.Exists())
{
// Create the SimpleMembership database without Entity Framework migration schema
((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
}
}
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
if (!WebSecurity.UserExists("Administrator"))
{
WebSecurity.CreateUserAndAccount("Administrator", "password");
}
if (!Roles.RoleExists("Administrator")) Roles.CreateRole("Administrator");
if (!Roles.GetRolesForUser("Administrator").ToList().Contains("Admin"))
{
Roles.AddUsersToRoles(new[] { "Administrator" }, new[] {"Admin" });
}
}
catch (Exception ex)
{
throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
}
}
}
So Basically, lazy loads the initialisation of the membership stuff. It is worth noting the InitializeDatabaseConnection call, the default is the name of the connection string, the UserProfile is the name of the users table (in our case UserProfile) and the next 2 fields specify the id and the username fields which is pretty much all simple membership needs in order to operate.
I have added a few lines below to show how you add other bits to the roles and users table.
OK, so if you need to use this functionality in a controller, decorate the controller class with the attribute :
[InitializeSimpleMembership]
and you use the WebSecurity class to get access to things like the user id e.g.:
WebSecurity.CurrentUserId;
Hope that helps !
A.
Just working on a project at home and thought I would use the simple membership in mvc 4 as it's pretty neat. We have a database already created so i'm using it from a database first perspective and thought i'd share the findings here in case someone else needs to do this. Most of this can be gleaned from creating a blank internet application and getting the bits necessary but thought I would put it in one place for ease of use.
the usual way to go about simple membership is to create an internet application which will do all the gubbins for you and create these tables :
In the old membership we used to run the aspnet_regsql command to register the membership tables. if you need to tables in this example, fear not, the scripts are below. PLEASE NOTE I TAKE NO RESPONSIBILITY IF THEY DESTROY YOUR DB. these were just generated with create script on the tables.
/****** Object: Table [dbo].[UserProfile] Script Date: 01/05/2013 23:09:00 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[UserProfile](
[UserId] [int] IDENTITY(1,1) NOT NULL,
[UserName] [nvarchar](56) NOT NULL,
PRIMARY KEY CLUSTERED
(
[UserId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
UNIQUE NONCLUSTERED
(
[UserName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[webpages_Membership] Script Date: 01/05/2013 22:55:24 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[webpages_Membership](
[UserId] [int] NOT NULL,
[CreateDate] [datetime] NULL,
[ConfirmationToken] [nvarchar](128) NULL,
[IsConfirmed] [bit] NULL,
[LastPasswordFailureDate] [datetime] NULL,
[PasswordFailuresSinceLastSuccess] [int] NOT NULL,
[Password] [nvarchar](128) NOT NULL,
[PasswordChangedDate] [datetime] NULL,
[PasswordSalt] [nvarchar](128) NOT NULL,
[PasswordVerificationToken] [nvarchar](128) NULL,
[PasswordVerificationTokenExpirationDate] [datetime] NULL,
PRIMARY KEY CLUSTERED
(
[UserId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[webpages_Membership] ADD DEFAULT ((0)) FOR [IsConfirmed]
GO
ALTER TABLE [dbo].[webpages_Membership] ADD DEFAULT ((0)) FOR [PasswordFailuresSinceLastSuccess]
GO
/****** Object: Table [dbo].[webpages_Roles] Script Date: 01/05/2013 22:56:30 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[webpages_Roles](
[RoleId] [int] IDENTITY(1,1) NOT NULL,
[RoleName] [nvarchar](256) NOT NULL,
PRIMARY KEY CLUSTERED
(
[RoleId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
UNIQUE NONCLUSTERED
(
[RoleName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[webpages_OAuthMembership] Script Date: 01/05/2013 22:56:56 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[webpages_OAuthMembership](
[Provider] [nvarchar](30) NOT NULL,
[ProviderUserId] [nvarchar](100) NOT NULL,
[UserId] [int] NOT NULL,
PRIMARY KEY CLUSTERED
(
[Provider] ASC,
[ProviderUserId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[webpages_UsersInRoles] Script Date: 01/05/2013 22:57:21 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[webpages_UsersInRoles](
[UserId] [int] NOT NULL,
[RoleId] [int] NOT NULL,
PRIMARY KEY CLUSTERED
(
[UserId] ASC,
[RoleId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[webpages_UsersInRoles] WITH CHECK ADD CONSTRAINT [fk_RoleId] FOREIGN KEY([RoleId])
REFERENCES [dbo].[webpages_Roles] ([RoleId])
GO
ALTER TABLE [dbo].[webpages_UsersInRoles] CHECK CONSTRAINT [fk_RoleId]
GO
ALTER TABLE [dbo].[webpages_UsersInRoles] WITH CHECK ADD CONSTRAINT [fk_UserId] FOREIGN KEY([UserId])
REFERENCES [dbo].[UserProfile] ([UserId])
GO
ALTER TABLE [dbo].[webpages_UsersInRoles] CHECK CONSTRAINT [fk_UserId]
GO
With the tables created, add the following to the web.config :
<roleManager enabled="true" defaultProvider="SimpleRoleProvider">
<providers>
<clear/>
<add name="SimpleRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData"/>
</providers>
</roleManager>
<membership defaultProvider="SimpleMembershipProvider">
<providers>
<clear/>
<add name="SimpleMembershipProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
</providers>
</membership>
Which adds the standard providers for simple membership. The project includes a filter attribute which you can place at the top of any of your controllers that need to make use of membership, the default class is the InitializeSimpleMembershipAttribute and looks like this:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
{
private static SimpleMembershipInitializer _initializer;
private static object _initializerLock = new object();
private static bool _isInitialized;
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Ensure ASP.NET Simple Membership is initialized only once per app start
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}
private class SimpleMembershipInitializer
{
public SimpleMembershipInitializer()
{
Database.SetInitializer<UsersContext>(null);
try
{
using (var context = new UsersContext())
{
if (!context.Database.Exists())
{
// Create the SimpleMembership database without Entity Framework migration schema
((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
}
}
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
if (!WebSecurity.UserExists("Administrator"))
{
WebSecurity.CreateUserAndAccount("Administrator", "password");
}
if (!Roles.RoleExists("Administrator")) Roles.CreateRole("Administrator");
if (!Roles.GetRolesForUser("Administrator").ToList().Contains("Admin"))
{
Roles.AddUsersToRoles(new[] { "Administrator" }, new[] {"Admin" });
}
}
catch (Exception ex)
{
throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
}
}
}
So Basically, lazy loads the initialisation of the membership stuff. It is worth noting the InitializeDatabaseConnection call, the default is the name of the connection string, the UserProfile is the name of the users table (in our case UserProfile) and the next 2 fields specify the id and the username fields which is pretty much all simple membership needs in order to operate.
I have added a few lines below to show how you add other bits to the roles and users table.
OK, so if you need to use this functionality in a controller, decorate the controller class with the attribute :
[InitializeSimpleMembership]
and you use the WebSecurity class to get access to things like the user id e.g.:
WebSecurity.CurrentUserId;
Hope that helps !
A.
Subscribe to:
Posts (Atom)