Overwrite the LoginWidget and Set DestinationPageUrl dynamically in Sitefinity - dynamic

I want to add some custom code during the login function, in particular i want to redirect the user after login to the previous page.
For example: i'm on page A , i want to download something from this page, but i'm not authorized. Then pops a popup with link to the login page. After successful login i'm back on page A.
For this purpose i want to overwrite the LoginWidged and to set value to"this.DestinationPageUrl" dynamically.
I read about similar issues here and here, but there isn't an example how to overwrite this LoginWidget class.
I create CustomLoginControl.cs file in my project and register as a new custom control, but after rendering it on the page, it didn't work. Login button does not make nothing. I'm not sure what exactly have to do and which of methods have to overwrite.
namespace SitefinityWebApp.UserControls
{
public class CustomLoginControl : Telerik.Sitefinity.Web.UI.PublicControls.LoginWidget
{
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
this.DestinationPageUrl = "http://previousPage.com";
base.Render(writer);
}
}
}
Can you give me an example how to overwrite this class to work properly.
Version: Sitefinity 5.0, Claims-based authentication

I've done something similar but instead of overriding the login control you can subscribe and capture the UnauthorizedAccess event, send the user to your login page with your redirect page as a query string parameter. You'll need to add a Global.asax / Global.asax.cs file to your project, then add this to the Application_Start function:
protected void Application_Start(object sender, EventArgs e)
{
Bootstrapper.Initialized += BootstrapperInitialized;
}
Then add these two functions:
private void BootstrapperInitialized(object sender, ExecutedEventArgs e)
{
if (e.CommandName == "Bootstrapped")
{
EventHub.Subscribe<IUnauthorizedPageAccessEvent>(OnUnauthorizedAccess);
}
}
private void OnUnauthorizedAccess(IUnauthorizedPageAccessEvent unauthorizedEvent)
{
var manager = ConfigManager.GetManager();
string loginPage = manager.GetSection<ProjectConfig>().DefaultSite.FrontEndLoginPageUrl;
var redirectParam = unauthorizedEvent.RedirectUrl.Replace(string.Format("{0}?ReturnUrl=", loginPage), string.Empty);
var escaped = Uri.EscapeDataString(redirectParam);
unauthorizedEvent.HttpContext.Response.Redirect(string.Format("{0}?ReturnUrl={1}", loginPage, escaped));
}
You will also need to set your default front end login page in the settings under Administration -> Settings -> Advanced -> Project -> DefaultSite and the FrontEndLoginPageUrl setting.
This works for me on a 6.3 site, not sure if this is available in Sitefinity 5 or not.

Related

Blazor Wasm Identity Login/Logout event

In a .Net 5 Blazor WASM app using the standard identity from the Wasm template, I want to do something when a user logs in (or logs out). I've tried the RemoteAuthenticatorView in Authentication.razor:
#page "/authentication/{action}"
#using Microsoft.AspNetCore.Components.WebAssembly.Authentication
<RemoteAuthenticatorView Action="#Action"
OnLogInSucceeded="OnLoginSucceeded"
OnLogOutSucceeded="OnLogoutSucceeded1"
/>
#code{
[Parameter] public string Action { get; set; }
public async void OnLoginSucceeded()
{
// do something
}
public void OnLogoutSucceeded1()
{
// do something
}
}
and also, I tried in a component (where I really want to take the action to merge a shopping basket) :
AuthenticationStateProvider.AuthenticationStateChanged += OnAuthenticationStateChanged;
private async void OnAuthenticationStateChanged(Task<AuthenticationState> task)
{
var user = (await task).User;
Console.WriteLine(DateTime.Now.ToString("hh:mm:ss:fff") + " InitialDataLoader -> OnAuthenticationStateChanged -> IsUserAuthenticated: " + user.Identity.IsAuthenticated);
}
I have breakpoints in each method and after I finally hit the Login breakpoint in both the RemoteAuthenticatorView and my component (it didn't break at all for a while), it now breaks but once only. If I logout - no logout event. If I login again, even as another user, I don't hit the breakpoints.
Is there a consistent method to generate or detect a login?
Turns out it was working ok, just the breakpoints were not working - no idea why not. I added Console.WriteLine messages to each & all events are hit correctly. So both techniques work as expected.

Notification pop-up add link to settings window

I've following code, this was copied from one of questions here on SOF,
private void showMyMessage() {
ApplicationManager.getApplication().invokeLater(() -> {
com.intellij.notification.Notification notification = GROUP_DISPLAY_ID_INFO
.createNotification("<html>TLogin failed", " Go to Settings to setup login data!</html>",
NotificationType.ERROR,
new NotificationListener.UrlOpeningListener(true));
Project[] projects = ProjectManager.getInstance().getOpenProjects();
Notifications.Bus.notify(notification, projects[0]);
});
}
I would like to have a link instead text "LINK!!!", what can you suggest ?
I think that I need to create action and add this action to my group GROUP_DISPLAY_ID_INFO, but this group is not in xml it's just in code exists.
If take my code above as an example, need to add right after new
NotificationListener.UrlOpeningListener(true))
addAction(new NotificationAction("Settings") {
#Override
public void actionPerformed (#NotNull AnActionEvent anActionEvent,
#NotNull Notification notification){
DataContext dataContext = anActionEvent.getDataContext();
Project project = PlatformDataKeys.PROJECT.getData(dataContext)
ShowSettingsUtil.getInstance().showSettingsDialog(project,
YOURCLASS.class);
}
Where yourclass.class is a class which implements Configurable interface
And now on click on Settings you will see opened settings window (yourclass.class)
private static void showMyMessage(String LINK) {
ApplicationManager.getApplication().invokeLater(() -> {
Notification notification = GROUP_DISPLAY_ID_INFO
.createNotification("<html>TLogin failed", " Go to Settings to setup login data!</html>",
NotificationType.ERROR,
new NotificationListener.UrlOpeningListener(true));
Project[] projects = ProjectManager.getInstance().getOpenProjects();
Notifications.Bus.notify(notification, projects[0]);
});
}
Just replace the link as a parameter, and use it like showMyMessage("http://google.com")
Also you don't need to config the group display id in xml, just write the id in code.

NoCache is not working as expected

I used an Action Filter named [NoCache] to disable the access of login page after login by pressing the browser back button. The code is given below.
public class NoCacheAttribute : ActionFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
filterContext.HttpContext.Response.Cache.SetValidUntilExpires(false);
filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
filterContext.HttpContext.Response.Cache.SetNoStore();
base.OnResultExecuting(filterContext);
}
}
Then i referred it in login page as shown below.
[HttpPost]
[NoCache]
public ActionResult Index(Login objLogin)
{
return RedirectToAction("Index", "Blood");
}
But the result was unexpected. Instead of redirecting to Blood/Index action, the control transfered to the url : http://localhost:4506/Account/Login?ReturnUrl=%2fBlood
How can i correct this ?. Thanks.
This probably related with Form Authentication feature. Do you need it? If not, just don't use it.
For more details, please refer to:
How to remove returnurl from url?

How do I navigate from one view to another in Caliburn.Micro?

So let me put it this way.
I have a LogInViewModel and a LogInView. There is a Login() method in the ViewModel that gets called if the user clicks on a button in the View. Now I want the dashboard to show if the login was successful. How do I do this? I can't find a clear answer to this in the documentation.
I assume that your dashboard is essentially your shell. In which case, you can bootstrap your LoginViewModel and in the Login method, after a successful login, you can show the DashboardViewModel and close the LoginViewModel using the Caliburn.Micro WindowManager.
Something like (using MEF):
Bootstrapper.cs
public class Bootstrapper : Caliburn.Micro.Bootstrapper<ILoginViewModel>
{
...
}
LoginViewModel.cs
public class LoginViewModel : Screen, ILoginViewModel
{
private readonly IWindowManager windowManager;
private readonly IDashboardViewModel dashboardViewModel;
[ImportingConstructor]
public LoginViewModel(IWindowManager windowManager, IDashboardViewModel dashboardViewModel)
{
this.windowManager = windowManager;
this.dashboardViewModel = dashboardViewModel;
}
public void Login()
{
// if login success...
this.windowManager.ShowDialog(this.dashboardViewModel);
this.TryClose();
}
}
I've just added a very simple login example SL4 project in my "lab repository" for Caliburn.Micro.
https://github.com/jenspettersson/Caliburn.Micro.Labs/tree/master/src/Login
It uses the Show class that Rob Eisenberg uses in his "Game Library" example to switch between views.
In the Login() method, it tells my Shell (your dashboard?) to show my LoginResultViewModel and sets the login result message.
yield return Show.Child<LoginResultViewModel>().In<IShell>().Configured(c => c.ResultMessage = "Successfully logged in!");
Check the code in my github repo.
I havent used Caliburn.Micro very much lately, so I am by no means an expert, but this way works for me.
//J
Edit: This answers how to navigate between views, if you want to show a "popup" to display if the login was successful, go with the other recomendations.

Can a SharePoint WebPart connect to a custom SharePoint WebPart

I need to consume a value passed by the default sharepoint filter webpart. I don't see how a custom sharepoint webpart can establish a connect and get data. Is this even possible?
Updated
The provider WebPart is a default SharePoint List Filter WebPart.
The consumer WebPart is a custom WebPart
This is the code I came up with, but the "connections" option is still greyed out on the SharePoint page. On the page, I have a SharePoint List Filter WebPart and my CustomPageViewer WebPart.
namespace PageViewerWithConnections.CustomPageViewer
{
[ToolboxItemAttribute(false)]
public class CustomPageViewer : System.Web.UI.WebControls.WebParts.WebPart
{
IFilterValues _filterVals;
[ConnectionConsumer("Consumer connection", "Consumer param")]
public void ConsumeFilter(IFilterValues filterValues)
{
_filterVals = filterValues;
}
Microsoft.SharePoint.WebPartPages.PageViewerWebPart objPageViewer;
protected override void CreateChildControls()
{
}
}
}
Reason's for this approach
My goal is to set a different URL to the page viewer Web Part based on the value I get from a SharePoint List Filter Web Part. It seems that the SharePoint List Filter WebPart cannot send data to a Page Viewer WebPart.
You'll need to create a consumer method on your custom webpart that takes an instance of IFilterValues as an argument and uses the ConnectionConsumerAttribute Attribute.
private IFilterValues _filterVals;
[ConnectionConsumer("Filter Consumer", "FilterConsumer")]
public void ConsumeFilter(IFilterValues filterValues)
{
_filterVals = filterValues;
}
Note that the consumption of the filter values occurs during the OnPreRender stage of the page lifecycle, so you'll need to override the OnRender method to act on any values consumed from the connection, or include the logic in the consumer method.
For more information, check out these links:
http://msdn.microsoft.com/en-us/library/ms494838(v=office.12).aspx
http://msdn.microsoft.com/en-us/library/ms469765.aspx
In the CreateChildControls you should call base.CreateChildControls();
Here is some working code:
List<IFilterValues> providers = new List<IFilterValues>();
protected override void CreateChildControls()
{
if (providers.Count > 0 && providers[0].ParameterValues != null)
{
this.FilterValue1 = providers[0].ParameterValues[0];
}
base.CreateChildControls();
}
[ConnectionConsumer("Provider WebPart", "IFilterValues", AllowsMultipleConnections = false)]
public void SetConnectionInterface(IFilterValues provider)
{
if (provider != null)
{
this.providers.Add(provider);
List<ConsumerParameter> parameters = new List<ConsumerParameter>();
parameters.Add(new ConsumerParameter("param1",
ConsumerParameterCapabilities.SupportsSingleValue | ConsumerParameterCapabilities.SupportsEmptyValue | ConsumerParameterCapabilities.SupportsAllValue));
provider.SetConsumerParameters(new ReadOnlyCollection<ConsumerParameter>(parameters));
}
}