login_decorator not working for ajax - decorator

I am using Ajax in my template. It calls a view (ajax_view()). I have applied login decorator on this view so that if user is not logged in then he should first be directed to login page.
But it is not working. Login decorators work on every view except for views that use Ajax.
How can I resolve this?

On ajax calls also the http response is actually a redirect to the login page, but your page will not redirect as this is an asynchronous call.
You probably want to do something like this:
def ajax_login_required(f):
def wrap(request, *args):
if request.user.is_authenticated():
return f(request, *args)
else:
if request.is_ajax():
return HttpResponse('false')
else:
return login_required(f)(request, *args)
return wrap
#ajax_login_required
def ajax_view(request):
#------some code here---------
Now after this, you gotta do a minor change in your javascript.
This might change according to your ajax call.
$.getJSON("/my_ajax_url",{},function(r){
if(!r){window.location='/accounts/login'}
})

Related

How to insert a modal Login form in the navigation bar

I'm building a new website and one of the requirements is to have the login form be a modal window.
I'm trying to include it in the top navigation bar and it's only being rendered if the user is not logged in.
If I delete the model and let an empty modal everything works perfectly but when I add it again it doesn't work, because the model of the page (in this case the index page) is a different one then the one from the modal login.
How can I add this modal window with it's on model inside the top navbar? Are there any alternatives?
P.S. I'm using Razor Pages and ASP.NET Core 2.2.
Thanks!
You need to use a view component:
public class LoginViewComponent : ViewComponent
{
public async Task<IViewComponentResult> InvokeAsync()
{
var model = await GetModelAsync();
return View(model);
}
public Task<LoginViewModel> GetModelAsync() =>
Task.FromResult(new LoginViewModel());
}
Then, create the view Views\Shared\Components\Login\Default.cshtml and add your login form code there. Finally, in your layout where you want the login form to be:
#await Component.InvokeAsync("Login")
You'll need a page or handler that can respond to the form post. You cannot post to a view component; that's just about rendering a partial view with it's own model in a self-contained way that can be dropped in. You should have a hidden input in your login form for a "return URL" which you'll fill with Request.Path. Then, on successful login, you redirect the user back to this URL. That way, the login will be seamless, as if they never let the page they were on.
On failure, you should simply redisplay the login form like you would do normally. It's easier and more seamless to just return this as the view. As such, you can piggy-back on the the login page's built-in post handler. Again, just add your return URL field and fill it with the return URL from the request, so that the user will eventually make it back to the page they were initially on when starting the login process.

Detecting redirect to a different URL

I am using ASP.NET MVC with AngularJs framework. In my home controller I'm checking if there is a valid license and if not, I'm re-directing to a page to import license with this code:
public ActionResult Index()
{
var retVal = _licenseProvider.ValidateExistingLicense();
if (!retVal.Item1)
{
Response.Redirect("DataMaintenance/ImportLicenses", true);
return View("DataMaintenance/ImportLicenses");
}
So, in my ImportLicenses controller I want to detect that I was re-directed vs. called from the menu. I found an older thread about redirecting to a different action, but that solution doesn't apply. What are my options here?
You have a couple of options here:
Add a query string parameter in the ImportLicenses action that
determines whether the user got here via a redirect or the menu
Set a TempData variable before redirecting your user to the
ImportLicenses action.
Use a Session variable
Read this for more information about passing data between Action methods.
It really depends on your constraints, there are a number of options. Without knowing much about your project. My first suggestion would be to drop a cookie before redirecting, then when the request comes in to the ImportLicenses action you can check for the check, and delete it, but include whether or not the cookie was found in your view model so you can reflect this in the UI.
There are other options like using session state, or a query string parameter. A querystring parameter could be just as effective as the cookie idea i mentioned above, and it would be a bit cleaner.
If you can provide more information about your use case, I may be able to expand my answer.
Hope this helps.
In the meanwhile I decided to do a little bit of cheating, but it worked. In the menu I changed the original call to this
dataMaintNodes.SubNodes.Add(new MenuMapNode() { LabelKey = "importLicense", Action = "ImportLicenses", Controller = "ImportLicenses", Area = "DataMaintenance", Icon = "", Roles = "IMPORTLIC" });
In other words, instead of normal Index action I introduced a different action. I added that new action to my controller and just set the ViewBag property to false when called from the menu and to true in the Index action that is called by Redirect. So, it's a cheating, but it works. I only wanted to display Cancel button on that modal dialog when I am calling from the regular menu and no Cancel button when called from the home controller. Now, my second problem is that Modal Dialog doesn't really prevent from escaping from it and continuing working with the application. So, we may want to introduce more logic.

Got error after logout from master page

I created the sample for role authentication in asp.net 2005. I created the login panel on my default.aspx page and after login it works fine. Iused the code as below for login
FormsAuthentication.RedirectFromLoginPage(txtUName.Text, true, urlpath);
FormsAuthentication.SetAuthCookie(txtUName.Text, true);
Response.Redirect(urlpath, false);
I used all required page links in a single master page that is shown after login.
I used the code in master page for "logout" like below on clicks of link button
try
{
Response.Redirect("~/Logout.aspx" );
}
catch (Exception ee)
{
return;
}
Now when I logout from master page I got an error like this
unable to evaluate expression because the code is optimized or native frame is on top of call stack
I have goggled but not got the solution. I am unable to find-out the reason behind this.
Please provide the proper solution.
Thanks
http://support.microsoft.com/kb/312629/en-us
To work around this problem, use one of the following methods:
•For Response.End, call the HttpContext.Current.ApplicationInstance.CompleteRequest method instead of Response.End to bypass the code execution to the Application_EndRequest event.
•For Response.Redirect, use an overload, Response.Redirect(String url, bool endResponse) that passes false for the endResponse parameter to suppress the internal call to Response.End. For example:
Response.Redirect ("nextpage.aspx", false);
If you use this workaround, the code that follows Response.Redirect is executed.
•For Server.Transfer, use the Server.Execute method instead.

asp.net mvc expected controller and action not getting invoked

I have a weird issue. I loaded a page using "LoadMyPageController" and there is an ajax_submit_button1 which can be used submit the page.
Also there is another ajax_submit_button2 to print the page. This button submits the view model of the page as a whole to the "PrintController" which has a "PrintData" action.
Now when I hit the "ajax_submit_button2", my PrintController.PrintData is not invoked. Instead when I check my fiddler tool the request is made as
http://localhost:18484/LoadMyPage/PrintData?Length=14
which is an invalid URL.
I have contructed my ajax_submit_button2 in such a way that it should invoke
http://localhost:18484/Print/PrintData?Length=14
But I don't know why LoadMyPage controller is present in my URL.
Any thoughts or comments would be appreciated. By any chance does asp .net MVC decides that it will take a default controller on its own if it can't find the controller action for any reason.
The code is a kind of tightly coupled so can't post it. I want to know if anyone experienced a problem like this.
This has nothing to do with the routing on the server since the request being made by the client has the wrong controller in it. I suspect that your code generating the url for the submit button is not correct -- i.e., not specifying the controller to be used -- or that you have a form around the submit button that is actually being invoked instead of (or in addition to) the ajax code. Note that if your submit handler doesn't return false, the default form action will be invoked and the form submitted normally. If you do have a form, make sure that the url on it is correct and that your submit handler returns false.
$('#printForm').submit( function() {
$.ajax({
url: $(this).attr('action'),
...
});
return false; // this is important!
});

ASP.NET MVC partial views and redirecting

I have a partial view called Login.ascx that has my login boxes that I include on a number of pages throughout my site. It works fine when the information is correct but I'm trying to do validation so if the login info is incorrect, I want to redirect the user back to the view they were in before to show them the login errors. What is the correct way of saying, return to the view you came from?
If a login fails from any page, I think I would direct them to a login view for the errors instead of the previous page. A dedicated login page is likely to have more UI space to display errors, etc. than a login control on another page. Having said that, you may want to include a returnUrl parameter to the Login action so that when the login is actually successful, the user is directed back to the place they were (or were attempting to get to).
Sounds like instead of asking how I do this, you should be asking yourself WHY am I doing it this way. Maybe it's a design decision rather than a technical question.
Though if you're really going to have one controller actions for multiple login pages you can try...
return Redirect(Request.UrlReferrer.ToString());
Or keep the route name in TempData and just use a RedirectToRoute(TempData["LoginRoute"]);
Both solutions have a bad code smell though.
Note that if you're not checking for cross-site injections that is just going to refer back to the other site. You may want to do some validation on the referring URL.
For the built-in Login method of the AccountController there is a parameter named returnUrl which you can use like so:
Return Redirect(returnUrl);
or
Return RedirectToAction(returnUrl);
if you specify the returnUrl parameter as a valid actionlink.
I recently had similar problems - you might be able to find something here...

Resources