Can not create Umbraco MembersMembershipProvider in unit test - c#

I am creating unit tests for my website base on Unit framework. In my unit test, I need to create a MembersMembershipProvider of Umbraco, but it threw null exception:
System.NullReferenceException : Object reference not set to an instance of an object.
at Umbraco.Web.Security.Providers.MembersMembershipProvider..ctor()
at Tests.Controllers.MemberControllerTests.Test_ValidateUser() in
This is my unit test:
[TestFixture]
public class Test_ProxyMembershipProvider
{
[Test]
public void Test_ValidateUser()
{
var s = new MembersMembershipProvider();
}
}
What should I fix or I missed something? Any help are highly appreciate!
Cheer!

The null reference occurs because the MembersMembershipProvider uses IMembershipMemberService in the constructor. If you use the constructor without parameters it will try to get the IMembershipMemberService from the ApplicationContext (which is null since you're running unittests). You can add a mocked version of this service to the constructor parameters:
var mServiceMock = new Mock<IMembershipMemberService>();
var s = new MembersMembershipProvider(mServiceMock.Object);
For more implementation details of MembersMembershipProvider check out the github sourcecode

I recently had the same issue. I was able to resolve the problem by adding an app.config file to my test project.
Within the app.config file, you will need the system.web/membership section. You also need a connectionStrings section, if you are using a Sql provider.
<configuration>
<connectionStrings>
<add name="MyDataBase"
connectionString="data source=localhost;Integrated Security=SSPI;Initial Catalog=MyDataBase"
providerName="System.Data.SqlClient" />
</connectionStrings>
<system.web>
<membership defaultProvider="UnitTestSqlMembershipProvider">
<providers>
<clear/>
<add
name="UnitTestSqlMembershipProvider"
type="Membership.Unit.Provider.UuuSqlMembershipProvider, Membership.Unit.Provider, Version=1.0.0.0, Culture=neutral"
connectionStringName="MyDataBase"
applicationName="mylittleapp"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
requiresUniqueEmail="true"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="3"
passwordAttemptWindow="10"
minRequiredPasswordLength="8"
minRequiredNonalphanumericCharacters="0" />
</providers>
</membership>
</system.web>
</configuration>
Additionally, if you want to Mock your provider, then you can create an interface for your custom provider
eg Mock _mbrInfrastructe = new Mock();
at this point you can lean on obj.Setup calls to add additional control over unit tests.

Related

SQLite & Entity Framework 6 "The underlying data provider failed to open"

When my Winforms application reaches the first Entity Framework data "request" I get the following error.
Message: The underlying provider failed to open.
InnerException: Data source cannot be empty.
My connection string is being built dynamically to cater for the user's %appdata% directory path. I am building it at first runtime and updating the app.config with the connection string once it is built. The code that handles this is below:
public void ConstructEntityFrameworkConnectionString(string dbFileName)
{
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if (config.ConnectionStrings.ConnectionStrings["RemManagerDBEntities"] == null)
{
// Specify the provider name, server and database.
var provider = "System.Data.SQLite.EF6";
var providerName = "System.Data.EntityClient";
var attacheddbfilename = dbFileName;
// Initialize the connection string builder for the underlying provider.
SqlConnectionStringBuilder sqlBuilder = new SqlConnectionStringBuilder {
AttachDBFilename = attacheddbfilename,
IntegratedSecurity = true,
MultipleActiveResultSets = true,
ConnectTimeout = 30,
ApplicationName = "RemManagerDBEntities"
};
// Build the SqlConnection connection string.
string providerString = sqlBuilder.ToString();
// Initialize the EntityConnectionStringBuilder.
EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder {
Provider = provider,
ProviderConnectionString = providerString,
Metadata = #"res://*/EntityFramework.RemManagerDBModel.csdl|res://*/EntityFramework.RemManagerDBModel.ssdl|res://*/EntityFramework.RemManagerDBModel.msl"
};
var cs = new ConnectionStringSettings("RemManagerDBEntities", entityBuilder.ConnectionString, providerName);
if (config.ConnectionStrings.ConnectionStrings["RemManagerDBEntities"] == null)
{
config.ConnectionStrings.ConnectionStrings.Add(cs);
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("connectionStrings");
}
}
}
An example connection string that it creates:
metadata=res://*/EntityFramework.RemManagerDBModel.csdl|res://*/EntityFramework.RemManagerDBModel.ssdl|res://*/EntityFramework.RemManagerDBModel.msl; provider=System.Data.SQLite.EF6; provider connection string="AttachDbFilename=C:\Users\MacbookPro\AppData\Roaming\RemManager\Datasource\RemManagerDB.db; Integrated Security=True; MultipleActiveResultSets=True; Connect Timeout=30; Application Name=RemManagerDBEntities"
The method is called as part of the main method in the program.cs file.
static void Main()
{
var conController = new ConnectionController();
conController.ConstructEntityFrameworkConnectionString($"{Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)}\\RemManager\\Datasource\\RemManagerDB.db");
// Start the application
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new RemManager());
}
I've got the following NuGet packages installed:
Entity Framework 6
System.Data.SQLite
System.Data.SQLite.EF6
System.Data.SQLite.Core
System.Data.SQLite.Linq
Initially I have based the setup procedure from the following site with an amendment made by the second link shown.
https://www.codeproject.com/Tips/1056400/Setting-up-SQLite-and-Entity-Framework-Code-First
https://github.com/ErikEJ/SqlCeToolbox/wiki/EF6-workflow-with-SQLite-DDEX-provider
Below is an example of the calls that I am making to the database via entity framework. When stepping through the code the exception begins on the db.tblGroups.Select line.
public class GroupController : IGroup
{
public List<tblGroup> SelectAllGroups()
{
using (var db = new RemManagerDBEntities())
{
return db.tblGroups.Select(g => g).ToList();
}
}
...
}
The final piece of the puzzle is the app.config. The current config is shown below.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<!-- See Datasource.ConnectionController for the connection string builder.-->
</connectionStrings>
<entityFramework>
<providers>
<provider invariantName="System.Data.SQLite" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
<provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
</providers>
</entityFramework>
<appSettings>
<add key="databaseFilePath" value="" />
<add key="ClientSettingsProvider.ServiceUri" value="" />
</appSettings>
<system.web>
<membership defaultProvider="ClientAuthenticationMembershipProvider">
<providers>
<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" />
</providers>
</membership>
<roleManager defaultProvider="ClientRoleProvider" enabled="true">
<providers>
<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" />
</providers>
</roleManager>
</system.web>
<system.data>
<DbProviderFactories>
<remove invariant="System.Data.SQLite.EF6" />
<add name="SQLite Data Provider (Entity Framework 6)" invariant="System.Data.SQLite.EF6" description=".NET Framework Data Provider for SQLite (Entity Framework 6)" type="System.Data.SQLite.EF6.SQLiteProviderFactory, System.Data.SQLite.EF6" />
<add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".NET Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
</DbProviderFactories>
</system.data>
</configuration>
For what else it is worth, entity framework is working from a database first configuration. I am also running Entity Framework 6.2 and SQLite 1.0.106.0.
I've tried my best to find a valid solution on other sites that caters for the fact that I am combining Entity Framework and SQLite, but I haven't been able to come up with much. When I take the SQLite out of the equation, I still haven't been able to come up with much. One of the better questions I had found was here, but I am already doing what the suggested answer recommends.
I had a similar problem earlier, except with localdb. The application has been working previously on the localdb, however this issue has started since I have been endeavouring toward making the application more self contained and user friendly (e.g. not needing to modify the exe.config manually once installed).
Any suggestions would be greatly appreciated.
You cannot use a SqlConnectionStringBuilder with SQLite, use SQLiteConnectionStringBuilder instead, and set the DataSource property to the database file name

Using a secondary membership provider in asp.net

I am going to use the default built in membership provider in my app. If the first provider does not validate the user then I want to try to validate the user against another provider.
I have my secondary provider set up in my web.config like this:
<membership>
<providers>
<add name="SecondaryMemberShipProvider"
type="System.Web.Security.ActiveDirectoryMembershipProvider,System.Web, Version 4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
enableSearchMethods="true"
connectionUserName="MyDoman\user"
connectionPassword ="password"
connectionStringName ="ADConnectionString" />
</providers>
</membership>
I added a class "SecondaryMemberShipProvider" that inherits from MembershipProvider. I am unsure of how I code the ValidateUser method on my new class.

ASP.NET Profile Properties - using C# MVC

I am using C# MVC using .NET 4.0
I am trying to implement the ASP.NET Profile Properties seen at
http://msdn.microsoft.com/en-us/library/2y3fs9xs.aspx
First, I added the following in my web.config file. Note that I am trying to store the Location for a given user:
<profile>
<properties>
<add name="Location" />
</properties>
<providers>
<clear />
<add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="/" />
</providers>
</profile>
Within my code, I used the following:
After I post, I used the following my in controller:
Profile.Location = model.Location;
I am getting an error, Cannot resolve 'Profile'. Has anybody used the Profile Property that can offer any assistance? Note that I wasn't even able to find the class that is mentioned in the article.
Thanks
A profile would have to belong to a User/Member so you would have to load or create a new User before adding any profile properties to it.
See this SO post on a similar question

MembershipService not initialized

following some example from Microsoft I created my custom MembershipProvider in my MVC application as
if (MembershipService == null) { MembershipService = new AccountMembershipService(new FcMembershipProvider()); }
and the web.config is configured as
<membership defaultProvider="FcMembershipProvider" userIsOnlineTimeWindow="15">
<providers>
<clear />
<add
name="FcMembershipProvider"
type="Fc.Web.WebAppMVC.Models.FcMembershipProvider"
connectionStringName="ApplicationServices"
enablePasswordRetrieval="true"
enablePasswordReset="true"
applicationName="FcWebMVC"
requiresQuestionAndAnswer="true"
writeExceptionsToEventLog="false" />
</providers>
</membership>
Problem is the Initialize method is not automatically called. any hint?
Thx
I think you need to get hold of your membership provider using the static Membership.Provider like so:
if (MembershipService == null) { MembershipService = new AccountMembershipService((FcMembershipProvider)Membership.Provider); }
(I put a cast in there which you may not need depending on what AccoundMembershipService is expecting.) This way ASP .NET's membership system should initialize it for you.
what is the class that implements "MembershipProvider" class ? beacause in your config file it's "FcMembershipProvider" and in the code it's AccountMembershipService.
I created a custom membership provider, I only implemented the "MembershipProvider" class, and added the config like you've done, I think you dont have to add code.

The Role Manager feature has not been enabled

Got the following ProviderException :
The Role Manager feature has not been enabled.
So far so good.
Is there somewhere a method that can be called to check if the Role Manager has been enabled or not?
You can do this by reading from the boolean property at:
System.Web.Security.Roles.Enabled
This is a direct read from the enabled attribute of the roleManager element in the web.config:
<configuration>
<system.web>
<roleManager enabled="true" />
</system.web>
</configuration>
Update:
For more information, check out this MSDN sample: https://msdn.microsoft.com/en-us/library/aa354509(v=vs.110).aspx
If you got here because you're using the new ASP.NET Identity UserManager, what you're actually looking for is the RoleManager:
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new ApplicationDbContext()));
roleManager will give you access to see if the role exists, create, etc, plus it is created for the UserManager
I found 2 suggestions elsewhere via Google that suggested a) making sure your db connectionstring (the one that Roles is using) is correct and that the key to it is spelled correctly, and b) that the Enabled flag on RoleManager is set to true. Hope one of those helps. It did for me.
Did you try checking Roles.Enabled? Also, you can check Roles.Providers to see how many providers are available and you can check the Roles.Provider for the default provider. If it is null then there isn't one.
I found this question due the exception mentioned in it. My Web.Config didn't have any <roleManager> tag. I realized that even if I added it (as Infotekka suggested), it ended up in a Database exception. After following the suggestions in the other answers in here, none fully solved the problem.
Since these Web.Config tags can be automatically generated, it felt wrong to solve it by manually adding them. If you are in a similar case, undo all the changes you made to Web.Config and in Visual Studio:
Press Ctrl+Q, type nuget and click on "Manage NuGet Packages";
Press Ctrl+E, type providers and in the list it should show up "Microsoft ASP.NET Universal Providers Core Libraries" and "Microsoft ASP.NET Universal Providers for LocalDB" (both created by Microsoft);
Click on the Install button in both of them and close the NuGet window;
Check your Web.config and now you should have at least one <providers> tag inside Profile, Membership, SessionState tags and also inside the new RoleManager tag, like this:
<roleManager defaultProvider="DefaultRoleProvider">
<providers>
<add name="DefaultRoleProvider" type="System.Web.Providers.DefaultRoleProvider, System.Web.Providers, Version=2.0.0.0, Culture=neutral, PublicKeyToken=NUMBER" connectionStringName="DefaultConnection" applicationName="/" />
</providers>
</roleManager>
Add enabled="true" like so:
<roleManager defaultProvider="DefaultRoleProvider" enabled="true">
Press F6 to Build and now it should be OK to proceed to a database update without having that exception:
Press Ctrl+Q, type manager, click on "Package Manager Console";
Type update-database -verbose and the Seed method will run just fine (if you haven't messed elsewhere) and create a few tables in your Database;
Press Ctrl+W+L to open the Server Explorer and you should be able to check in Data Connections > DefaultConnection > Tables the Roles and UsersInRoles tables among the newly created tables!
If you are using ASP.NET Identity UserManager you can get it like this as well:
var userManager = Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
var roles = userManager.GetRoles(User.Identity.GetUserId());
If you have changed key for user from Guid to Int for example use this code:
var roles = userManager.GetRoles(User.Identity.GetUserId<int>());
<roleManager
enabled="true"
cacheRolesInCookie="false"
cookieName=".ASPXROLES"
cookieTimeout="30"
cookiePath="/"
cookieRequireSSL="false"
cookieSlidingExpiration="true"
cookieProtection="All"
defaultProvider="AspNetSqlRoleProvider"
createPersistentCookie="false"
maxCachedResults="25">
<providers>
<clear />
<add
connectionStringName="MembershipConnection"
applicationName="Mvc3"
name="AspNetSqlRoleProvider"
type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<add
applicationName="Mvc3"
name="AspNetWindowsTokenRoleProvider"
type="System.Web.Security.WindowsTokenRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</providers>
</roleManager>
Here is the code that you need to put in your Account Controller in MVC5 and later
to get the list of roles of a user:
csharp
public async Task<ActionResult> RoleAdd(string UserID)
{
return View(await
UserManager.GetRolesAsync(UserID)).OrderBy(s => s).ToList());
}
There is no need to use Roles.GetRolesForUser() and enable the Role Manager Feature.

Categories