I'm wondering if it is possible to achieve the following.
Within an MVC application -
Have a link which queries a database for some values, sets those values as session variables and then opens a pop-up window(which is an asp.net webform within the MVC app)
It's basically to allow us to run Crystal Reports, the link would set the Report ID in a session variable which would then be accessible in the asp.net webform.
My confusion is the setting of the session variable on click of the link and then opening the popup.
Can it be done and if so any links or pointers?
Edit:
Javascript
<script language="javascript" type="text/javascript">
function flagInappropriate(postId) {
var url = "/Home/FlagAsInappropriate/" + postId;
$.post(url, function(data) {
if (data) {
alert("True")
} else {
// callback to show error/permission
}
});
}
Controller
namespace MvcApplication1.Controllers
{
[HandleError]
public class HomeController : Controller
{
[AcceptVerbs("POST")]
public bool FlagAsInappropriate(int id)
{
// check permission
bool allow = true;
// if allow then flag post
if (allow)
{
// flag post
return true;
}
else
{
return false;
}
}
public ActionResult Index()
{
ViewData["Message"] = "Welcome to ASP.NET MVC!";
return View();
}
public ActionResult About()
{
return View();
}
}
}
It can be done, yes. I've achieved something similar for the purposes of generating reports (predominantly so the report URL is hidden from the user and so some tracking and authentication could be achieved using once-off tokens). My solution was as follows:
Perform an AJAX call to a Web Method in your application to set the relevant session variable(s).
Return a value from the Web Method to indicate whether it was successful.
For the "success" event handler of the AJAX call, open your relevant ASPX page to generate the report.
Simple as that. :)
Here's some sample code to attach the click event and do the AJAX call, based on your amended question:
Click to test AJAX call
<script type="text/javascript">
$(document).ready(function () {
$(".flag").click(function () {
flagInappropriate($(this).attr("id").split("-")[1]);
});
});
function flagInappropriate(postId) {
var url = "/Home/FlagAsInappropriate/" + postId;
alert(url);
$.post(url, function (data) {
if (data) {
alert(data);
} else {
// callback to show error/permission
}
});
}
</script>
Related
I am trying to call an action method without affecting the view. I call the following action method
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public void Index(LoginModel login)//, string returnUrl)
{
if (ModelState.IsValid &&
System.Web.Security.Membership.ValidateUser(login.UserName, login.Password))
{
FormsAuthentication.SetAuthCookie(login.UserName, login.RememberMe);
login.JavascriptToRun = "updateForm()";
}
// handle error
}
by doing this
$('#loginBtn').click(function () {
var success = false;
var form = $('#loginForm');
var token = $('input[name="__RequestVerificationToken"]', form).val();
$.ajax({
url: $(this).data('url'),
type: 'POST',
data: {
__RequestVerificationToken: token,
LoginModel: "#Model"
},
success: function (result) {
alert("logged in");
}
});
});
The form is in a separate view which also contains above JS-code snippet.
Everything works fine except for that the entire page reloads and since the actionmethod is void this turns out blank. I do not want anything to happen to the webpage, only to change js code snippet stored in a model which BTW is an empty function as of now.
I've looked at related posts such as ASP.NET MVC - How to call void controller method without leaving the view? but I am none the wiser.
Feels like I'v hit a wall and others' input would be much appreciated. Cheers!
You can use ActionResult as a data type for Index() Action and use View() to return your javascript into it. (return JavaScriptResult())
Check out this too:
Working example for JavaScriptResult in asp.net mvc
I am using MVC3, ASP.NET4.5, C#, Razor, Ajax
I have implemented an Ajax.Actionlink. All works well.
However, since I am also using Membership Services, I will get logged out of the system if I do not use it for say 20 mins. If one is on the Ajax page, and one clicks an Ajax link, the Ajax returns, within the TargetDiv, the Login page and not the correct partial view.
I suspect that if the app has expired then the response needs to override the ajax response, and return the full login page.
How can I solve this please.
You can use a custom authorize attribute to handle the situation.
public class AjaxAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
var request = filterContext.HttpContext.Request;
var response = filterContext.HttpContext.Response;
if (request.IsAjaxRequest())
{
response.StatusCode = 590; //custom status code, might as well be 401, dont know if that would violate any proncipal
filterContext.Result = new EmptyResult();
}
else
{
base.HandleUnauthorizedRequest(filterContext);
}
}
}
add some js codes in master page to handle the custom status code.
$(function () {
return $(document).ajaxError(function (e, xhr, opts) {
if (590 == xhr.status) {
return document.location = document.location;
}
});
});
use it as any [Authorize] attribute for the ajax actions you like to be authorized
public class HomeController : Controller
{
[AjaxAuthorize]
public JsonResult AjaxMethod()
{
return Json(new {message = "Hello"}, JsonRequestBehavior.AllowGet);
}
}
The custom Authorize filter will handle the unauthorized request and issue an empty
result with status code 590
The response will be caught as ajaxerror since the statuscode is 5**
The document will be reloaded (assuming the page is an authenticated one), as such will be redirected to login page.
Hope this helps
I have a view (Index.cshtml) with a grid (Infragistics JQuery grid) with an imagelink. If a user clicks on this link the following jquery function will be called:
function ConfirmSettingEnddateRemarkToYesterday(remarkID) {
//Some code...
//Call to action.
$.post("Home/SetEnddateRemarkToYesterday", { remarkID: remarkID }, function (result) {
//alert('Succes: ' + remarkID);
//window.location.reload();
//$('#remarksgrid').html(result);
});
}
Commented out you can see an alert for myself and 2 attempts to refresh the view. The location.reload() works, but is basically too much work for the browser. The .html(result) posts the entire index.cshtml + Layout.cshtml double in the remarksgrid div. So that is not correct.
This is the action it calls (SetEnddateRemarkToYesterday):
public ActionResult SetEnddateRemarkToYesterday(int remarkID) {
//Some logic to persist the change to DB.
return RedirectToAction("Index");
}
This is the action it redirects to:
[HttpGet]
public ActionResult Index() {
//Some code to retrieve updated remarks.
//Remarks is pseudo for List<Of Remark>
return View(Remarks);
}
If I don't do window.location.reload after the succesfull AJAX post the view will never reload. I'm new to MVC, but i'm sure there's a better way to do this. I'm not understanding something fundamental here. Perhaps a nudge in the right direction? Thank you in advance.
As you requesting AJAX call, you should redirect using its response
Modify your controller to return JSONResult with landing url:
public ActionResult SetEnddateRemarkToYesterday(int remarkID) {
//Some logic to persist the change to DB.
var redirectUrl = new UrlHelper(Request.RequestContext).Action("Index", "Controller");
return Json(new { Url = redirectUrl });
}
JS Call:
$.post("Home/SetEnddateRemarkToYesterday", { remarkID: remarkID }, function (result) {
window.location.href = result.Url
});
After Ajax post you need to call to specific Url..
like this..
window.location.href = Url
When using jQuery.post the new page is returned via the .done method
jQuery
jQuery.post("Controller/Action", { d1: "test", d2: "test" })
.done(function (data) {
jQuery('#reload').html(data);
});
HTML
<body id="reload">
For me this works. First, I created id="reload" in my form and then using the solution provided by Colin and using Ajax sent data to controller and refreshed my form.
That looks my controller:
[Authorize(Roles = "User")]
[HttpGet]
public IActionResult Action()
{
var model = _service.Get()...;
return View(model);
}
[Authorize(Roles = "User")]
[HttpPost]
public IActionResult Action(object someData)
{
var model = _service.Get()...;
return View(model);
}
View:
<form id="reload" asp-action="Action" asp-controller="Controller" method="post">
.
.
.
</form>
Javascript function and inside this function I added this block:
$.ajax({
url: "/Controller/Action",
type: 'POST',
data: {
__RequestVerificationToken: token, // if you are using identity User
someData: someData
},
success: function (data) {
console.log("Success")
console.log(data);
var parser = new DOMParser();
var htmlDoc = parser.parseFromString(data, 'text/html'); // parse result (type string format HTML)
console.log(htmlDoc);
var form = htmlDoc.getElementById('reload'); // get my form to refresh
console.log(form);
jQuery('#reload').html(form); // refresh form
},
error: function (error) {
console.log("error is " + error);
}
});
I have two user controls on the page and one of the user control has this text aread.
which is used to add a note and but when they click add note button the page reloads.
I do not want the page to reload ,i was looking for an example which this is done without
postback.
Thanks
i tired doing this using JSON , but it throws the following error
The HTTP verb POST used to access path '/Documents/TestNote/Documents/AddNote' is not allowed.
<script type="text/javascript">
$(document).ready(function() {
$("#btnAddNote").click(function() {
alert("knock knock");
var gnote = getNotes();
//var notes = $("#txtNote").val();
if (gnote == null) {
alert("Note is null");
return;
}
$.post("Documents/AddNote", gnote, function(data) {
var msg = data.Msg;
$("#resultMsg").html(msg);
});
});
});
function getNotes() {
alert("I am in getNotes function");
var notes = $("#txtNote").val();
if (notes == "")
alert("notes is empty");
return (notes == "") ? null : { Note: notes };
}
</script>
</asp:Content>
Something like this would give you the ability to send data to an action do some logic and return a Json result then you can update your View accordingly.
Javascript Function
function AddNote(){
var d = new Date(); // IE hack to prevent caching
$.getJSON('/MyController/MyAction', { data: "hello world", Date: d.getTime() }, function(data) {
alert(data);
// call back update your view here
});
}
MyController Action
public virtual JsonResult MyAction(string data)
{
// do stuff with your data here, which right now my data equals hello world for this example
return Json("ReturnSomeObject");
}
What you want is AJAX update. There will always be a postback (unless you are satisfied with simple Javascript page update that does not save on the server), but it won't be the flashing screen effect any more.
We would like to implement a web form that automatically saves content at regular intervals.Something similar to gmail/google docs auto save funcationality.
Can some one suggest how to implement this using ASP.NET MVC + jQuery?
jQuery Forms plugin and an ASP.NET MVC action should do the job:
public ActionResult SaveDraft(FormCollection form)
{
// TODO: Save the form values and return a JSON result
// to indicate if the save went succesfully
return Json(new { success = true });
}
And in your View just invoke this action periodically:
setInterval(function() {
$('#theFormToSave').ajaxSubmit({
url : 'SaveDraft',
success: function (data, textStatus) {
if (data.success) {
alert('form successfully saved');
}
}
});
}, 30000);