Skip to content

Define page which is automatically loaded after successful login dynamically from server side

Victor Tomaili edited this page May 3, 2021 · 1 revision

Basic Building Blocks Series: Within the basic building blocks series over time I will add all the little things which someone who just starts with Serenity Framework would have to spend a lot of time figuring it out him/herself.

What you get with this article:

Sometimes, you would like to configure the page which is automatically loaded after successful login dynamically on some conditions (e.g. user name or role) from server-side. By default, this is going to "/" which will go to the DashboardController and load the dashboard.

With this article, you can set the loaded page dynamically from server-side.


Within AccountPage.cs, create a new class for the custom Serviceresponse:

    public class LoginServiceResponse  : ServiceResponse
    {
        public string redirectURL { get; set; }
    }

Also within AccountPage.cs, modify the Login ServiceResponse to be like this:

public Result<LoginServiceResponse> Login(LoginRequest request)
        {
            return this.ExecuteMethod(() =>
            {
                request.CheckNotNull();

                if (string.IsNullOrEmpty(request.Username))
                    throw new ArgumentNullException("username");

                var username = request.Username;

                if (WebSecurityHelper.Authenticate(ref username, request.Password, false))
                {
                    var sr = new LoginServiceResponse();
                    sr.redirectURL = "../Content/Content";   // *** Your custom redirect target URL goes here. You have to step up one folder with "../" and then dive down into the module folder structure. Here I have a module called Content... ***
                    return sr;
                }

                throw new ValidationError("AuthenticationError", Texts.Validation.AuthenticationError);
            });
        }

And within AccountLogin.cshtml, change the LoginButton click function to be like this:

$('#LoginButton').click(function (e) {
	e.preventDefault();
	if (!_this.validateForm()) {
		return;
	}
	var request = _this.getSaveEntity();

	Q.serviceCall({
		url: Q.resolveUrl('~/Account/Login'),
		request: request,
		onSuccess: function (response) {
			var q = Q.parseQueryString();
			var returnUrl = q['returnUrl'] || q['ReturnUrl'];
			if (returnUrl) {

				// *** The standard returnURL querystring parameter is the root of the project - so if it is something else, then you were logged out at some other page and after login again you must be redirected back to that page ***
				var rootPathName = window.location.pathname.replace('Account/Login', '');

				if (String(returnUrl) != rootPathName ) {

					var hash = window.location.hash;
					if (hash != null && hash != '#')
						returnUrl += hash;

					window.location.href = returnUrl;
				}
				else {
					// *** Standard returnURL queryString parameter, redirect to custom url given from server-side ***
					var redirectURL = response.redirectURL;
					var hash = window.location.hash;
					if (hash != null && hash != '#')
						redirectURL += hash;

					var resolvedURL = Q.resolveUrl(redirectURL);
					window.location.href = resolvedURL;
				}

			}
			else {
				// *** in case returnURL is null, redirect to custom url given from server-side ***
				var redirectURL = response.redirectURL;
				var hash = window.location.hash;
				if (hash != null && hash != '#')
					redirectURL += hash;

				window.location.href = Q.resolveUrl(redirectURL);
			}
		}
	});
});

Update 2020-04-18: Bug fixed so that it also works when project is deployed within a subfolder of a web page.

This should do it. Hint: As I never have waited until I got logged out at an arbitrary url within the SF app, this is not yet fully tested.

With kind regards,

John

Clone this wiki locally