I've created a on WebProvisioned event.
At the end i want to do a redirect to a custom page. But this is not as easy as i thougt.
I did:
string url = "CustomAdminPage.aspx";
SPUtility.Redirect(url, SPRedirectFlags.RelativeToLayoutsPage, currentContext);
The event is Synchronous, so i can use the Httpcontext in the contstructor.
How can i make a redirect from my webprovisioned event?
Maybe this would help:
public override void ItemAdding(SPItemEventProperties properties)
{
if (DateTime.Now.Hour > 9 || DateTime.Now.Hour < 17)
{
properties.Status = SPEventReceiverStatus.CancelWithRedirectUrl;
properties.RedirectUrl = "/_layouts/EventReceiver/CustomError.aspx";
}
}
I've found this here
Best regards!
Related
I need to remove an object from the PageHandler Header Controls collection in my page template.
I can use the below script to do so at the widget view level, however the one I need to remove has not yet been added at that point, so I need to move it right before it's consumed.
The only accessible place for it that I could find is in my template file - right before #Html.Section("head"). I'm trying to remove the default canonical URL for this template only (some crazy routing stuff going on in this site... don't ask).
var pageHandler = this.ViewContext.HttpContext.Handler.GetPageHandler();
foreach (var c in pageHandler.Header.Controls)
{
if (c != null && c is System.Web.UI.HtmlControls.HtmlLink)
{
System.Web.UI.HtmlControls.HtmlLink mylink = (System.Web.UI.HtmlControls.HtmlLink)c;
if (mylink.Attributes["rel"] == "canonical")
{
pageHandler.Header.Controls.Remove(mylink);
}
}
}
When I try to use this in the template file inside the <head> tag pageHandler.Header is null.
1 - Am I accessing this object in the wrong way for this particular template level? If so, what's the proper object reference?
2 - Is it simply not set yet because of some behind-the-scenes page construction order in Sitefinity? If so, where could/should I handle accessing this object?
3 - Something else is going on entirely?
I AM NOT ASKING HOW TO FIX A NULL REFERENCE EXCEPTION
I understand that the object is null and am trying to find where in the Sitefinity viewmodel at this level this data might be found.
The canonical url is set in Page_PreRenderComplete event which fires after your code in the view has executed.
What I would do is create a new widget, e.g. CanonicalUrlRemover.
In its Index method find the Page object and subscribe to its PreRenderComplete event. Then in the event handler remove the canonical url.
public ActionResult Index()
{
var page = HttpContext.CurrentHandler.GetPageHandler();
page.PreRenderComplete += Page_PreRenderComplete;
return new EmptyResult();
}
private void Page_PreRenderComplete(object sender, System.EventArgs e)
{
var page = sender as System.Web.UI.Page;
if (page != null)
{
var headerControls = page.Header.Controls;
foreach (var c in headerControls)
{
if (c != null && c is System.Web.UI.HtmlControls.HtmlLink)
{
System.Web.UI.HtmlControls.HtmlLink mylink = (System.Web.UI.HtmlControls.HtmlLink)c;
if (mylink.Attributes["rel"] == "canonical")
{
headerControls.Remove(mylink);
}
}
}
}
}
Just drop the widget in this particular page template and you are good to go.
The code works but is silly.
When the View is returned to the user the page scrolls to the companyId anchor.
Silly is that I have to expose another public action with another route (without 'terms')
I want to redirect to /terms/companyId but then I get an ambigiousAction exception that this action with same routes already exists...
How to solve that dilemma if possible not change the first route?
[HttpGet("~/terms/{companyId}")]
public IActionResult Home(string companyId})
{
string url = Url.Action(nameof(HomeForRedirect), new { companyId}) + "#conditions";
return new RedirectResult(url);
}
[HttpGet("{companyId}")]
public IActionResult HomeForRedirect(string companyId)
{
Viewbag.CompanyId = companyId;
return View(nameof(Home));
}
If I'm understanding your code, you essentially want the URL /terms/{companyId} to redirect to /{controller}/{companyId}#conditions? The easiest path would be to attach both routes to the same action and do the redirect in a conditional. Something like:
[HttpGet("{companyId}", Order = 1)]
[HttpGet("~/terms/{companyId}", Order = 2)]
public IActionResult Home(string companyId)
{
if (Context.Request.Path.StartsWith("/terms"))
{
var url = Url.Action(nameof(Home), new { companyId }) + "#conditions";
return Redirect(url);
}
ViewBag.CompanyId = companyId;
return View();
}
An even better method would be to simply do the redirect directly in IIS. There's a not insignificant amount of processing that needs to occur to handle a request in ASP.NET Core machinery, and it's totally wasted effort simply to redirect. Use the URL Rewrite module in IIS to set up your redirect for this URL, and then your application doesn't have to worry about it at all. You just have your normal run-of-the-mill Home action that returns a view, and everything will just work.
A few other notes since it seems like you're new to this:
It's better to use the Route attribute rather than the more specific HttpGet etc. The default is GET.
Return the controller methods like Redirect rather than instances of IActionResult (i.e. new RedirectResult(...)).
The default is to return a view the same name as the action. So, assuming your action is Home, you can just do return View(), rather than return View(nameof(Home)).
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.
i've got the following url construction from my cms
domain.de/cmsfolder/page1/page2/function/my-news-headline
or
domain.de/cmsfolder/page1/function/my-reference-headline
i want to stripe out the function so that my url is
domain.de/cmsfolder/page1/page2/my-news-headline
or
domain.de/cmsfolder/page1/my-reference-headline
and didn't result in an 404 error.
can someone tell me if this is possible and how?
or perhaps it is possible to stripe out "function" out of any url of my page?
Best regards and thank you in advance
not an elegant solution, but this will work in case you only got 1 action ('myfunction') in your pages controller:
add this to Page_Controller:
private $actionName;
private static $allowed_actions = array (
'myfunction'
);
static $url_handlers = array(
'' => 'myfunction'
);
public function init(){
parent::init();
$urlParams = $this->getURLParams();
if(isset($urlParams['Action'])) { //might not be set when coming from '/' or '/home'
$this->actionName = $urlParams['Action'];
}
}
public function myfunction() {
//do something here with $this->actionName
}
now, when you navigate to domain.de/cmsfolder/page1/page2/my-news-headline, $actionName will be set to 'my-news-headline', and myfunction is called to work with it.
I'm using a filter that checks the user's browser/version upon arrival to the site. If they use an unsupported browser, I save the URL they intended to reach into a ViewData called "RequestedURL" and redirect to a view telling them their browser is old. This view gives the user the ability to proceed by clicking a link. The URL of this link is being populated by the ViewData attribute of "RequestedUrl" that was set in the filter.
Filter:
/// <summary>
/// If the user has a browser we don't support, this will present them with a page that tells them they have an old browser. This check is done only when they first visit the site. A cookie also prevents unnecessary future checks, so this won't slow the app down.
/// </summary>
public class WarnAboutUnsupportedBrowserAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var request = filterContext.HttpContext.Request;
//this will be true when it's their first visit to the site (will happen again if they clear cookies)
if (request.UrlReferrer == null && request.Cookies["browserChecked"] == null)
{
//give old IE users a warning the first time
if ((request.Browser.Browser.Trim().ToUpperInvariant().Equals("IE") && request.Browser.MajorVersion <= 7) ||
(request.Browser.Browser.Trim().ToUpperInvariant().Equals("Chrome") && request.Browser.MajorVersion <= 22) ||
(request.Browser.Browser.Trim().ToUpperInvariant().Equals("Mozilla") && request.Browser.MajorVersion <= 16) ||
(request.Browser.Browser.Trim().ToUpperInvariant().Equals("Safari") && request.Browser.MajorVersion <= 4))
{
filterContext.Controller.ViewData["RequestedUrl"] = request.Url.ToString();
filterContext.Result = new ViewResult { ViewName = "UnsupportedBrowserWarning" };
}
filterContext.HttpContext.Response.AppendCookie(new HttpCookie("browserChecked", "true"));
}
}
}
View reference to the ViewData:
Thanks for letting me know.
Most Urls work fine. The problem comes when the user enters a URL that has a parameter in it. For example:
[WarnAboutUnsupportedBrowser]
public ActionResult Index(string providerkey)
If the Url the user entered is "../Controller/Foo/providerkey", the Url that populates in the view is "Controller/Foo" with the missing parameter that is required to access the page.
How can I make sure that the URL in the view is the entire URL the user originally entered?