Partial View Link on MVC LoginPage not working (User not logged-in/Authorized yet) - asp.net-mvc

I am working on a website in ASP.NET MVC and working on LoginPage. On the LoginPage, we also have 'Forgot Password' link and clicking that link opens a Modal-popup (bootstrap) with content being returned as PartialView.
Problem I am facing is, when I click on 'Forgot Password' link on the page, Index method of Login controller gets called instead of ForgotPassword related method which results in LoginPage being returned in modal popup.
[AllowAnonymous]
[System.Web.Services.WebMethod()]
public ActionResult ForgotPassword()
{
return PartialView("_ForgotPassword");
}
It seems like some sort of authentication issue because if I login using our old Login Page (it's an .aspx page) and then try to manually go to a new ASP.NET MVC page, all the link with partialView on login Page works fine.
Anyone else had this issue? any pointer would be appreciated.
Thanks
Edit 1: Javascript used to call modal popup
function AttachPopup() {
$('.modal-popup').click(function (event) {
event.preventDefault();
event.stopImmediatePropagation();
var url = $(this).attr('data-content-url');
var modalId = $(this).attr('data-target-model');
var target = $(this).attr('data-target-content');
$.ajax({
url: url,
type: 'POST',
datatype: "json",
cache: false,
traditional: true,
success: function (data) {
$(target).empty();
$(target).append(data);
$(modalId).modal('show');
}
});
});
}
url comes correct but still index is called.

When the AllowAnonymous attribute, the onAuthorization method of AuthorizeAttribute simply ignores authorization and authentication checking. Even if you had a global authorization filter. It should still work. A user had a similar issue. Please check out this link

As mentioned, I was converting an aspx website to MVC. In Web.config, we had
<authorization>
<deny users="?" />
</authorization>
This was taking precedence over MVC [AllowAnonymous] attribute. Commenting out above code, fixed my problem.
Word of caution: When you do that, do check that your website is secure with [Authorize] attribute

Related

How to redirect to login page if AbpAuthorize is failed in asp.net mvc?

I have modified the asp.net boilerplate mvc template css, but somehow, I might mess up with the code. Now if the user is not logged in/not authorized, the error pops out, click ok, instead of redirecting to the login page, it redirects to the default $urlRouterProvider in the app.js. Here is part of the app config:
app.config([
'$stateProvider', '$urlRouterProvider', '$locationProvider', '$qProvider',
function ($stateProvider, $urlRouterProvider, $locationProvider, $qProvider) {
$locationProvider.hashPrefix('');
$urlRouterProvider.otherwise("/");
$qProvider.errorOnUnhandledRejections(false);
$stateProvider
.state('login', {
url: '/Account/Login',
templateUrl:'/Views/Account/Login.cshtml'
})
.state('dashboard', {
url: '/',
templateUrl: '/App/Main/views/dashboard/dashboard.html',
data: { pageTitle: '' }
})
]);
Can any one please explain what happens behind the scenes? What is the magic code that redirects the user to the login page regardless of what you defined in the angularjs?
Thanks in advance!
After days of search, I found out the reason why it did not work is because the response is not handled by HandleUnauthorizedRequest method. It is supposed to redirect to the path you defined in the startup when receiving 401 unauthorized status.
And why it did not trigger the HandleUnauthorizedRequest is because I removed the AbpMvcAuthorize in Home controller.

How to get OAuth working on MVC4 mobile

I have been struggling to get OAuth to work on my MVC4 mobile application.
I basically
Created an MVC4 Mobile application
Created an MVC4 Web application
Copied the AccountController, AccountModel, InitializeSimpleMembershipAttribute and all account views into my MVC4 Mobile application
Enabled Google and Facebook OAuth providers
I also ensured RoleManager was initialized according to simplemembershipprovider-not-working, although I do not think that was important. ( I needed it for some role-based security I was testing)
Disabled ajax ( I think) by setting data-ajax="false":
using (Html.BeginForm("ExternalLogin", "Account",new RouteValueDictionary { { "ReturnUrl", ViewBag.ReturnUrl } }, FormMethod.Post, new Dictionary<string, object> { { "data-ajax", false } })) (This did not seem to have any effect on the page - so I may be doing something wrong here...)
I can get to the LogIn view /Account/Login, and when I click the google button, the debugger breaks into public ActionResult ExternalLogin(string provider, string returnUrl)
However - the public ActionResult ExternalLoginCallback(string returnUrl) is never hit.
Visually, I get the jquery mobile "page loading" animation - then I get "Error Loading Page"
I have two questions:
How can I get more information when I try to figure out what happens?
How can I get OAuth working on my MVC4 mobile site?
BTW: Both sites target .Net4.0
OK - so I figured out the answer - the cuplrit was indeed the ajax in jQuery mobile.
I modified my _layout.cshtml so that it can render a custom script after loading jQuery, but before loading jQuery mobile:
#Scripts.Render("~/bundles/jquery","~/scripts/RemoveHashFromWindowLocation")
#RenderSection("beforeJqueryMobile", required: false);
#Scripts.Render( "~/bundles/jquerymobile")
#RenderSection("scripts", required: false)
Then I modified my Login.cshtml so that it contains the section:
#section BeforeJqueryMobile {
#Scripts.Render("~/scripts/disable-ajax.js")
}
And finally, I added the following to my scripts folder:
disable-ajax.js:
$(document).bind("mobileinit", function () {
$.mobile.ajaxEnabled = false;
});
RemoveHashFromWindowLocation.js: (Thanks to Facebook Oauth Login With Jquery Mobile #_=_)
if (window.location.hash == "#_=_")
window.location.hash = "";
Voila - OAuth working with jQuery mobile. :-)
The above answer from espenalb does work if your site loads directly to the login page, however if you have say a home page and then and a link to the login page(which uses the same layout), you will get an error loading page when you click one of the social login buttons.
To fix this add
<script>
$('#login-link').live("click", function () {
$.mobile.ajaxEnabled = false;
});
</script>
to the bottom of your mobile layout page, this will attach an event handler that will disable ajax to the login link.

MVC - Identify Page Form Authentication time out

we are developing MVC3 application such that most of our action methods are called via ajax calls and return partialviews. we come across a situation where we need to identify if the action method is called from Form Authentication time out.
public ActionResult LogOn()
{
// I want to return View("LogOn"); if the call is coming from
// Form Authentication time out
return PartialView(Model);
}
here is my web.config looks like:
<authentication mode="Forms">
<forms loginUrl="~/Home/LogOn" timeout="20" />
</authentication>
Appreciate your input.
Your action will never be hit if the authentication cookie has timed out. The forms authentication module directly redirects to the logon page. One possibility for you to detect this happening from client scripting is to set a custom HTTP header in the controller action serving this logon page:
public ActionResult LogOn()
{
var model = ...
Response.AppendHeader("X-LOGON", "true");
return View(model);
}
and then when performing your AJAX request you could use the getResponseHeader method on the XHR object in order to verify if the X-LOGON header was set meaning that the server redirected to the logon page. In this case in your success AJAX handler instead of simply injecting the server response into the DOM or relying on the returned JSON you could show some alert message informing the user that his authentication session has timed out and he needs to login again. Another possibility is to automatically redirect him to the logon page using the window.location.href method:
$.ajax({
url: '/home/some_protected_action',
success: function (data, textStatus, XMLHttpRequest) {
if (XMLHttpRequest.getResponseHeader('X-LOGON') === 'true') {
// the LogOn page was displayed as a result of this request
// probably timeout => act accordingly
}
}
});
There is no way from the server to distinguish between the user loading the page normally versus performing a page refresh.
There are ways to tell the difference between a regular request and an AJAX request, but it doesn't sound like that's what you're asking for.
There is no easy way but if you apply Post-Redirect-Get, I am not sure you will have that problem.

ASP.NET MVC multiple forms, staying on same page

I have forms located in multiple areas in my layout page (not nested).
I have a partial view which performs a post to controller action.
What action result do I return in that post to keep the user on the current page?
Is jquery/ajax my only option? I would rather a solution that didn't depend on javascript, maybe even a solution that degrades nicely.
You can use the Request.Referrer property to see what page the user has come from and then just use that to redirect them back there.
This does introduce other issues, e.g. losing ModelState, so you'll have to design for that. Also note that some users can block sending referrer information in their requests to the server - so the Referrer property can be null.
I would recommend using AJAX and then falling back on this.
You just need to do a RedirectToAction("") back to your main view.
To post a form without submitting the whole page, which refreshes the browser, you need to use Ajax/jQuery. The degraded solution is to submit the whole page like you would with a normal form.
Here's how I do it with jQuery.
Html:
<div id="RequestButtonDiv">
<button id="RequestButton" name="Request" type="button">Request</button>
</div>
This calls AddToCart on my Request controller when the RequestButton button is clicked. The response is placed inside the RequestButtonDiv element.
<script type="text/javascript">
$(document).ready(function () {
$('#RequestButton').click(function (event) {
$('#RequestButton').text('Processing...');
$('#RequestButton').attr('disabled', true);
submitRequest();
});
});
function submitRequest() {
$.ajax({
url: '<%: Url.Action("AddToCart", "Request", new { id = Model.RowId, randomId = new Random().Next(1, 999999) } ) %>',
success: function (response) {
// update status element
$('#RequestButtonDiv').html(response);
}
});
}
</script>
Controller action:
public ActionResult AddToCart(int id)
{
var user = AccountController.GetUserFromSession();
user.RequestCart.AddAsset(id);
return View("~/Views/Assets/Details_AddToCart.ascx");
}
The controller returns a partial view. You could also return Content("some stuff") instead.
Holler if you have questions or need more detail.

Redirect to an ASP.NET MVC page problem after POST request from Silverlight

In an ASP.NET MVC application I have a CartController with this AddToCart action:
public RedirectToRouteResult AddToCart(Cart cart, decimal productId,
string returnUrl)
{
Product product = productsRepository.Products
.FirstOrDefault(p => p.prodID == productId);
cart.AddItem(product);
return RedirectToAction("Index", new { returnUrl });
}
When a user submits a POST request ("Add to Cart" button) to this action from a plain ASP.NET MVC view, everything goes well: the Product is added to the Cart and the user is automatically redirected to a Cart/Index page.
If the product is submitted from a Silverlight app (which is inside an ASP.NET MVC view) it is successfully added to the Cart as well, but the there is no redirection in this case.
What is the problem? Maybe it is due to the fact that all requests from a Silverlight are asynchronous (if I'm not mistaken), and the request from a general ASP.NET MVC view is synchronous by nature? How it can affect the redirection?
In any case, how this problem could be solved?
Edited (added):
My code for sending a post request from a Silverlight app:
//first build a "paramstring" in the format "productId=126504" and then post it using this
WebClient wc = new WebClient();
wc.Headers["Content-type"] = "application/x-www-form-urlencoded";
wc.UploadStringAsync(new Uri("http://localhost:10930/Cart/AddToCart"), "POST", paramstring, "http://localhost:10930/Products");
The WebClient you are using to send the POST request will automatically follow the redirects performed on the server and return the HTML and everything ends in the success callback. If you want to redirect the user browser to this page you shouldn't use WebClient. You need javascript to submit a <form>. Silverlight allows you to execute javascript, so you could use it to dynamically generate and submit a form, or if the form already exists in the DOM set the values of the input fields and submit it.
Here's an example of how you could do this. Add the following javascript function to the same page hosting the Silverlight application:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript">
function addToCart(productId, returnUrl) {
var form = $(document.createElement('form'))
.attr('action', '/products/addtocart')
.attr('method', 'post')
.append(
$(document.createElement('input'))
.attr('type', 'hidden')
.attr('name', 'productId')
.val(productId)
)
.append(
$(document.createElement('input'))
.attr('type', 'hidden')
.attr('name', 'returnUrl')
.val(returnUrl)
);
$('body').append(form);
form.submit();
}
</script>
And then inside your Silverlight application whenever you decide to invoke the POST action:
HtmlPage.Window.Invoke("addToCart", "123", "http://example.com/someReturnUrl");
You may add other parameters if necessary.

Resources