How to use custom AuthorizeAttribute with AJAX - c#

With help of fellow friends I managed to find a solution for my problem from this topic: Reusable way to allow an account to be used by a single person at a time
I have a SingleLogin class which inherits from AuthorizeAttribute and implements a custom AuthorizeCore method for the purpose of re-usability of my single-login code:
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
bool isAuthorized = base.AuthorizeCore(httpContext);
if (isAuthorized)
{
int userId = (int)WebSecurity.CurrentUserId;
using (var db = new UsersContext())
{
if ((httpContext.Session.SessionID != db.getSessionId(userId))
|| db.getSessionId(userId) == null)
{
WebSecurity.Logout();
isAuthorized = false;
httpContext.Response.Redirect("/Home/Index");
}
}
}
return isAuthorized;
}
Everything works fine except my JsonResult action:
[HttpPost]
public JsonResult MessageSave(string message)
{
bool messageSaved = false;
int userId = (int)WebSecurity.CurrentUserId;
message = HttpUtility.HtmlEncode(message);
// Model method - adding chat log - db
db.addChatLog(message, userId);
messageSaved = true;
return Json(new { messageSaved = messageSaved });
}
This method is triggered by Ajax POST call which you can see in code example below. Just basic POST.
EDIT 3
Please check these images: http://imgur.com/a/Cjael .. Hm I guess POST does trigger, but have no idea why does my alert not work when I try to test it before $.ajax ... As you can see in response I do get Home/Index page but I am not redirected to home/index immediately(text stays inside of textBox and page just waits..), I have to push enter one more time to be redirected.. Very strange.
EDIT2
Seems like I can't even access my jQuery even after I get logged out. I put some alerts inside of my .js file.
I have a separate .js file which is then put in my View as <script src="~/Scripts/custom/homeChat.js"></script> . I pass the Razor values from View into my JS file via HTML5 data-.
My textBox element #txtMsg, triggers my jQuery event, therefore when I am logged out it probably doesn't recognize my textBox element anymore, and doesn't trigger my jQuery event?
Element that triggers .js in view is:
#Html.TextBox("txtMsg")
JS:
$("#txtMsg").keypress(function (e) {
//when enter
if (e.which == 13) {
alert("ALERT DOESNT TRIGGER");
$.ajax({
type: "POST",
url: url,
data: JSON.stringify({ message: input }),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
if (data.messageSaved) {
$("#txtMsg").val("");
}
else {
window.location.href = urlhome;
}
}
});
}
}
});
So if you can't even come into your event, how can you even know something went wrong? I have this ˙HandleUnauthorizedRequest but you are required that you can get into your jQuery event(in my case .keypress in the js code above) for this to work if I understand right.
EDIT: Additional explanation
So let me explain the scenario. If I login with my username "john" from Firefox and again with username "john" from chrome, next action I do in Firefox, it will log me out and redirect me to Home/Index, because someone else made a new login in Chrome.
That is ok. Since you are not logged in anymore, you get redirected normally to your Home/Index if your action is normal ActionResult and returns view.
The problem I have is, that I have some other functionality in the page, which uses Ajax POST, and since you are logged out you can't POST to that JsonResult action therefore you can't even receive callback of error, which redirects you to Home/Index. I put some alerts into my JS, but no alert triggers which is normal, because I am not allowed on that page anymore anyway. If I want that my onEnter textbox redirects me to Home/Index I have to press enter twice. Is that all that could be done?
I am interested in best approach for this AJAX problem. I don't know how I should call it, but as I read from my previous topic it is called "handling AJAX timeouts"?
Thank you very much.

You can handle errors on AJAX request this way
$.ajax({
type: "POST",
url: url,
data: JSON.stringify({ message: input }),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
if (data.messageSaved) {
$("#txtMsg").val("");
}
else {
window.location.href = urlhome;
}
},
error: function(xhr, status, error) {
// TODO: may be check error or status or xhr.statusCode()
window.location.href = urlhome;
}
});
jQuery $.ajax() docs

If understand it correctly you want to handle the unauthorized ajax request.
In that case you can override the HandleUnauthorizedRequest method in your attribute:
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
filterContext.Result = new JsonResult();
}
else
{
filterContext.Result = new HttpStatusCodeResult((int)HttpStatusCode.Forbidden);
}
}

Related

How to redirect to main log in page when a session expires in Asp.net?

I have developed an application in Asp.Net MVC with C# Programming Language and using code first Approach, The application is deployed and everything is working properly except a minor issue that i am facing.
When the session is expired it does not redirect the user to the main login page of the application, where i want that the application should redirect the user to the main login page while the session is expired.
How is it possible?
There are numerous examples for the functionality that you want to achieve, but I wanted to give you a basic scenario of how you would do a redirect to the login page when a session expires or the user logs out:
Assuming you have setup your session, when a user will logout, the controller will have a Logout method:
public ActionResult Logout()
{
Session.Abandon();
Session.Clear();
return RedirectToAction("LoginPage", "Login");
}
This would destroy the session variables and redirect the user to the Login page.
Now when a session expires, you can do something like this:
public ActionResult SessionCheck()
{
string message = string.Empty;
if (Session["UserName"] == null)
{
message = "Session expired. Please Login again";
}
return Json(message, JsonRequestBehavior.AllowGet);
}
You can check for this method throughout your program using AJAX or you could use SessionState.
I prefer to use AJAX so I am giving you a simple example:
function IsSessionActive()
{
var url ="/Login/SessionCheck";
var param = {};
param = JSON.stringify(param);
var result = getResultPost(url, param);
if (result != "")
{
alert("Session has expired, Please login again");
//Redirect Here
window.location="#Url.Action("LoginPage", "Login")";
return true;
}
}
function getResultPost(url, param) {
var result;
$.ajax({
url: url,
type: "POST",
async: false,
dataType: "json",
data: param,
contentType: "application/json; charset=utf-8",
success: function (data, textStatus) {
result = data;
},
error: function (e) {
result = "Error";
}
});
return result;
}
And finally call this in your View like:
$(document).ready(function () {
if (IsSessionActive()) return false;
})
This will check for the session on every page that you call this method and if the session is expired, it will alert the user and redirect to the Login page. You can customize your own styles like a modal or customized alert box to show the user that their session has expired. I hope this helps.

Jquery .post method is sending a null value. How to pass actual value to controller?

I have a controller that applies to an edit view in asp.net MVC. I have an actionlink that sends the row Id to the controller which then brings back the correct row to see in the associated view.
I then have a partial view below that. That also requires a parameter in order to bring associated data from another table.
I have a Jquery .post call that runs after the page is loaded. I can alert out and show the exact value I want to send to the controller.
$(document).ready(function () {
var url = "/Home/MmsAndNotes";
var Uc = $("#Id").serialize();
alert(Uc);
$.post(url, {Id: Uc}, function (data) {
alert("what is Uc now? " + uc); //just for testing
});
})
I have also used it this way.
$(document).ready(function () {
var url = "/Home/MmsAndNotes";
var Uc = $("#Id").val();
alert(Uc);
$.post(url, Uc, function (data) {
});
})
the alerts come up and show the value I want. However, when the .post call runs, it sends a null value. Here is my controller.
public ActionResult MmsAndNotes(string Id)
{
//Declare LogisticsVM for individual policy info
LogisticsMMS_NotesVM model;
if(uc == null)
{
return Content("uc is empty.");
}
int val = Convert.ToInt32(uc);
using (Db db = new Db())
{
LogisticsMMS_NotesDTO dto = db.LogisticsMMS.Find(val);
//confirm policy exists
if (dto == null)
{
return Content("This policy cannot be found." + val);
}
model = new LogisticsMMS_NotesVM(dto);
}
return PartialView(model);
}
It always returns as uc is empty. I repeat, when the alerts come up. I get the correct value to send to the controller. But once it sends, something happens and it converts to null. HELPPPPP.. please .. I'm losing my mind over this one.
I don't know why, but changing my $.post() call to an $.ajax({}) call solved the issue. As you can see above, I had the $.post call. Using this instead,
$.ajax({
type: "POST",
url: "/Home/MmsAndNotes",
dataType: 'text',
data: { Id: Uc }
});
Solved it. I thought Jquery's shortened calls worked the same way. They certainly might, but doing it this way was the only way it worked for me.
P.S. Thanks Tyler (above) for your comments.
this solution should be work :
$(document).ready(function () {
$.ajax({
url: '/Home/MmsAndNotes',
type: 'GET',
dataType: "html",
data: { uc : $("#Id").val() },
success: function (result) {
code here
}
});
})
You need to verify if $("#Id").val() is not empty

Submit form through ajax and callback an alert

I submit a form using ajax request. The form is actually inside a modal popup. The submission works well. But I want it to show an alert that said the form is submitted and close the current modal. Here is my code:
$('#btnBookRoom').click(function() {
$.ajax({
url: "/Booking/BookRoom",
type: "POST",
data: $('#frmRoomBooking').serialize(),
datatype: "json",
sucess: function(data) {
alert('Room Booking Success');
$('#roomBookingModal').modal('hide');
}
});
});
Controller:
public ActionResult BookRoom(RoomBookingInputModel roomBooking)
{
var domain = new RoomBooking
{
GuestId = roomBooking.GuestId
};
db.RoomBookings.Add(domain);
db.SaveChanges();
return Json(domain, JsonRequestBehavior.AllowGet);
}
The alert doest shows and the modal also not hiding.
sucess isn't a valid callback in jQuery's ajax method. You need to change it to success.
Or better, use promise API to bind a success handler (as AJAX callbacks are already deprecated):
$.ajax({ ... })
.then(function() {
alert('Room Booking Success');
$('#roomBookingModal').modal('hide');
});

Push Table to screen

I have an AJAX request when a branch of my JSSTree is clicked
$("#jstree").bind("select_node.jstree", function(evt, data)
{
var idArgument = data.node.text;
$.ajax(
{
type: "POST",
url: "WebForm1.aspx/brancheSelectionnee",
data: JSON.stringify({ id: idArgument }),
contentType: "application/json; charset=utf-8",
success: function(msg)
{
;
}
});
});
So, I call this function, which make a new "page" (because it's static) and call a function that return a System.Web.UI.WebControls.Table.
public static string brancheSelectionnee(string id)
{
var page = (WebForm1)HttpContext.Current.CurrentHandler;
System.Web.UI.WebControls.Table tableau = page.brancheSelectionneeNonStatique(id);
var stringWriter = new StringWriter();
using (var htmlWriter = new HtmlTextWriter(stringWriter))
{
tableau.RenderControl(htmlWriter);
}
string tableauString=stringWriter.ToString();
return "randomstring";
}
Big problem here: My "tableau" is updated, with what I want (I see this with the htmlWriter) but.. I don't know how put it in my screen!
I have it in my C# code, but I want it in the screen, and not just here.
I have "tableauArticle" which is a real System.Web.UI.WebControls.Table, in my ASP.net code.
I tried some things, like putting "tableauArticle" as Static, then
tableauArticles = tableau;
But I didn't see any changement. I think that I updated a table in the page that I don't display
I think that the main problem is that my pagee isn't refresh or I do my tables wrong.
You do an AJAX request, so there is no page refresh. You just get a string (with HTML) back from your server method. You then have to manually put that string on your page. This happens in the success callback function which in your code is empty. As first step try something like this:
success: function(msg)
{
$('<div class="newtable">').html(msg).appendTo('body');
}
On the server-side your method brancheSelectionnee needs the AjaxMethod attribute so that it can be called with AJAX:
[Ajax.AjaxMethod()]
public static string brancheSelectionnee(string id)
(It also should return tableauString; not "randomstring", right?. And I am not sure if you can use the HttpContext.Current.CurrentHandler there, but that is for a second step if the basic AJAX stuff works.)
Here is one tutorial for all this which gives you an overview.
For the answer, it is 100% Raidri solution :
$('#tableauArticles').empty();
$('<div class="newtable">').html(msg.d).appendTo('#tableauArticles');

update field or redirect page using jquery and asp.net mvc

Im new to jquery and stuck with what i want to achieve.
Heres what I want to do using jquery and asp.net mvc.
click a submit button
this calls an action method called LogOn in the controller Account
if the call allows users to log in succesfully redirect to a url (sepecified by LogOn)
if it fails replace a div(with id="error") with "sorry error occured"
so far I tried this:
$("#submit")
.button()
.click(function () {
$.ajax({
type: "POST",
url: "Account/LogOn",
dataType: "json",
success: function (data, textStatus) {
if (data.redirect) {
// data.redirect contains the string URL to redirect to
window.location.href = data.redirect;
}
else {
// data.form contains the HTML for the replacement form
$("#error2").replaceWith(data.error);
}
}
});
});
how do I construct the relevant bits in the action method? to make this work?
and is the jquery code ok? i suspect prob not.
Thanks
If you want to redirect asp.net page at same directory , you can by Jquery/Java script by this :
$("#ctl00_iframecontent_BtnCancle").click(function () {
window.location = "IncSLAList.aspx?bi=37";
});
and
To redirect to Another page of project , can use :
window.location.href = "http://ImageUpload/Welcome.aspx?
Your jQuery is almost correct:
Don't call .button() (unless you're using jQuery UI and want to do that)
Add return false; at the end of the click handler to prevent the browser from submitting normally.
In the action, you would either return Json(new { redirect = str }) or return Json(new { error = str }).

Categories