I have an Umbraco install with a licensed version of Umbraco forms. On my local development all pages are very fast to load
However when I have transferred to a live server every page is OK except for the form page.
If I take out the @renderAction() for the form it loads fine but with it in it takes 6 seconds (looking at using umbDebugShowTrace=true) just to load that action.
The trace log shows the form views as loading fast - so the issue must be between the controller and loading the views.
I have tried creating a new one field form but this also loads slow so it shouldn't be anything in the form I have created either.
There is nothing reporting in the log files as an error or file permission problem as I have had issues with that before.
I have redeployed all files without this helping either.
I haven't tried caching no. Does it work on forms, they have a submitted and non submitted state?
The strange thing is the speed it loads on a local Visual studio environment compared to the server. When I load the page the server load isn't high it just takes a long time.
I've figured out what is making the form load slow.
The forms plugin is interacting with my custom Membership provider for some reason and alongside basic authentication (on a staging site) it causes a slow down.
It isn't an issue now as on the live site it will work fine as disabling the basic auth makes it work.
However why is Umbraco Forms using the membership provider and what is it doing that causes such a delay
Carl after almost 5 years, your post has helped me to fix my Umbraco forms page load time problem(them being extremely slow), so thank you very much for your answer. I am posting my fix details here so hopefully I'll also help another fellow Developer and maybe my future self!
Details;
Umbraco version 7.15.4 assembly: 1.0.7381.11453
Umbraco Forms version: 7.4.1
I originally thought this was something to do with some Umbraco forms bug but then I found out each time I was going from one Umbraco forms page to another I was seeing the following exception, which means my system was trying to get the member data from Umbraco db, even though I don't use built-in Umbraco membership provider as I don't store any members in the standard Umbraco membership system;
> ERROR umbraco.cms.businesslogic.member.Member An error occurred in
> GetCurrentMember System.InvalidOperationException: No member object
> found with username [email protected] at
> umbraco.cms.businesslogic.member.Member.GetCurrentMember()
Then I realized I still had this setting in my web.config;
My new custom membership provider class - see that I have only implemented GetUser as I only need that;
using System;
using System.IdentityModel.Claims;
using System.Linq;
using System.Web.Security;
using Umbraco.Core.Security;
using Umbraco.Web.Security.Providers;
namespace ProjectName.Web.Presentation.Security
{
/// <summary>
/// Custom membership provider that we use to replace the normal Umbraco one as we are not storing any members in the standard Umbraco membership system.
/// Instead members are logging in using SSO and using claims based auth, claims are provided by both MyProject SSO and additionally come from Crm Api
/// It is almost entirely unimplemeted apart from the GetUser method which is called by various umbraco functions especially from a few places in Umbraco Forms
/// All other methods will throw a NotImplemented Exception
/// </summary>
/// <remarks>
/// We have to inherit the Umbraco membership provider rather than the standard System.Web.Security.Membership otherwise umbraco roles don't work
/// when protecting content using Umbraco public access UI due to this Umbraco issue https://github.com/umbraco/Umbraco-CMS/issues/5469
/// </remarks>
public class ProjectNameMembershipPvovider : MembersMembershipProvider
{
public override string DefaultMemberTypeAlias
{
get
{
throw new NotImplementedException();
}
}
//public override MembershipUser GetUser(string username, bool userIsOnline)
//{
// //return base.GetUser(username, userIsOnline);
//}
/// <summary>
/// Returns a user based on the username.
/// As we do not have any backing store to look up user details this will only ever return a user if username requested is the currently logged in user.
/// In this case we can get the details from the current claims principle, otherwise we will return null
/// </summary>
/// <param name="username"></param>
/// <param name="userIsOnline"></param>
/// <returns></returns>
public override MembershipUser GetUser(string username, bool userIsOnline)
{
//If no username then just return null
if (string.IsNullOrWhiteSpace(username))
{
return null;
}
//check requested user is the same as the current logged in user
if (System.Security.Claims.ClaimsPrincipal.Current?.Identity?.Name == username)
{
var cp = System.Security.Claims.ClaimsPrincipal.Current;
//Try and extract crm contactId from the users claims (where we put it during login)
var crmIdClaim = cp.Claims.FirstOrDefault(i => i.Type == Services.IdentityService.CrmContactIdClaim)?.Value;
Guid? crmContactId = null;
if (crmIdClaim != null)
{
crmContactId = Guid.Parse(crmIdClaim);
}
var user = new MyProjectMembershipUser(
Membership.Provider.Name, //Providername
cp.Claims.FirstOrDefault(i => i.Type == "name")?.Value, //Name
cp.Claims.FirstOrDefault(i => i.Type == ClaimTypes.NameIdentifier)?.Value, // provideruserkey
cp.Claims.FirstOrDefault(i => i.Type == Services.IdentityService.EmailClaim)?.Value, //email
null, //password question
null, //comment
true, //isApproved
false, //isLockedOut
DateTime.MinValue, //creation date
DateTime.Now, //last login date
DateTime.Now, //last activity date
DateTime.MinValue, //last pasword change
DateTime.MinValue, //last lockout date
crmContactId);
return user;
}
else
{
return null;
}
}
#region #region NotImplemented Properties and Methods
public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
{
throw new NotImplementedException();
}
public override bool ChangePassword(string username, string oldPassword, string newPassword)
{
throw new NotImplementedException();
}
public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
{
throw new NotImplementedException();
}
public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
{
throw new NotImplementedException();
}
public override bool DeleteUser(string username, bool deleteAllRelatedData)
{
throw new NotImplementedException();
}
public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
{
throw new NotImplementedException();
}
public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
{
throw new NotImplementedException();
}
public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
{
throw new NotImplementedException();
}
public override int GetNumberOfUsersOnline()
{
throw new NotImplementedException();
}
public override string GetPassword(string username, string answer)
{
throw new NotImplementedException();
}
public override string GetUserNameByEmail(string email)
{
throw new NotImplementedException();
}
public override string ResetPassword(string username, string answer)
{
throw new NotImplementedException();
}
public override bool UnlockUser(string username)
{
throw new NotImplementedException();
}
public override void UpdateUser(MembershipUser user)
{
throw new NotImplementedException();
}
public override bool ValidateUser(string username, string password)
{
throw new NotImplementedException();
}
protected override MembershipUser PerformCreateUser(string memberTypeAlias, string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
{
throw new NotImplementedException();
}
protected override bool PerformChangePassword(string username, string oldPassword, string newPassword)
{
throw new NotImplementedException();
}
protected override bool PerformChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
{
throw new NotImplementedException();
}
protected override string PerformGetPassword(string username, string answer)
{
throw new NotImplementedException();
}
protected override string PerformResetPassword(string username, string answer, string generatedPassword)
{
throw new NotImplementedException();
}
#endregion NotImplemented Properties and Methods
}
}
And finally ProjectNameMembershipUser is as follows;
using System;
using System.Web.Security;
namespace ProjectName.Web.Presentation.Security
{
/// <summary>
/// Represents a logged in ProjectName user, inherits standard membership user and adds additional fields that we need populated from claims
/// </summary>
public class ProjectNameMembershipUser:MembershipUser
{
public Guid? CrmContactId { get; private set; }
public ProjectNameMembershipUser(string providerName,
string name,
object providerUserKey,
string email,
string passwordQuestion,
string comment,
bool isApproved,
bool isLockedOut,
DateTime creationDate,
DateTime lastLoginDate,
DateTime lastActivityDate,
DateTime lastPasswordChangedDate,
DateTime lastLockoutDate,
Guid? crmContactId) : base(
providerName, name, providerUserKey, email, passwordQuestion, comment,
isApproved, isLockedOut, creationDate, lastLoginDate, lastActivityDate,
lastPasswordChangedDate, lastLockoutDate)
{
CrmContactId = crmContactId;
}
}
}
Forms taking a long time to load
Hi,
I have an Umbraco install with a licensed version of Umbraco forms. On my local development all pages are very fast to load
However when I have transferred to a live server every page is OK except for the form page.
If I take out the @renderAction() for the form it loads fine but with it in it takes 6 seconds (looking at using umbDebugShowTrace=true) just to load that action.
The trace log shows the form views as loading fast - so the issue must be between the controller and loading the views.
I have tried creating a new one field form but this also loads slow so it shouldn't be anything in the form I have created either.
There is nothing reporting in the log files as an error or file permission problem as I have had issues with that before.
I have redeployed all files without this helping either.
Any help appreciated.
Thanks
Carl
Have you tried to use caching, i.e., macro caching? It helped me alot.
(however debug mode and caching does not work well together so remember to set it to false)
Good luck Martin
Hi Martin
I haven't tried caching no. Does it work on forms, they have a submitted and non submitted state?
The strange thing is the speed it loads on a local Visual studio environment compared to the server. When I load the page the server load isn't high it just takes a long time.
Thanks
Carl
Ok.
I've figured out what is making the form load slow.
The forms plugin is interacting with my custom Membership provider for some reason and alongside basic authentication (on a staging site) it causes a slow down.
It isn't an issue now as on the live site it will work fine as disabling the basic auth makes it work.
However why is Umbraco Forms using the membership provider and what is it doing that causes such a delay
Thanks
Carl
Carl after almost 5 years, your post has helped me to fix my Umbraco forms page load time problem(them being extremely slow), so thank you very much for your answer. I am posting my fix details here so hopefully I'll also help another fellow Developer and maybe my future self!
Details;
I originally thought this was something to do with some Umbraco forms bug but then I found out each time I was going from one Umbraco forms page to another I was seeing the following exception, which means my system was trying to get the member data from Umbraco db, even though I don't use built-in Umbraco membership provider as I don't store any members in the standard Umbraco membership system;
Then I realized I still had this setting in my web.config;
And then your comment made perfect sense, and I simply created a custom membership provider and updated this web.config setting to following;
My new custom membership provider class - see that I have only implemented GetUser as I only need that;
And finally ProjectNameMembershipUser is as follows;
is working on a reply...