How to stop an MVC RedirectToRouteResult JavaScript? - javascript

I am designing a site and am trying to be compatible with javascript turned off or on.
I have a Controller Action named as follows...
public RedirectToRouteResult AddWorkAssignment(int id)
{
// delegate the work to add the work assignment...
return RedirectToAction("Index", "Assignment");
}
and my jQuery I do a post
$('#someButton').click(function() {
var id = $('#whereTheIDIs').val();
$.post('/Assignment/AddWorkAssignment/' + id);
return false;
});
but the RedirectToAction on the controller will do just that.... how do I stop the redirect to occur, or how do I structure the controller and page to handle this, because I want the redirect to occur if javascript is turned off.

Change your controller to something like this:
public ActionResult AddWorkAssignment(int id)
{
// do work to add the work assignment....
if (Request.IsAjaxRequest())
return Json(true);
return RedirectToAction("Index", "Assignment");
}
You could create your own filter attribute too... much like the AcceptVerbs attribute.
HTHs
Charles
EDIT: AjaxRequest ActionMethodSelectorAttribute attribute
Kickstart from here
public class AjaxRequest : ActionMethodSelectorAttribute
{
public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
{
if (controllerContext == null)
throw new ArgumentNullException("controllerContext");
return controllerContext.HttpContext.Request.IsAjaxRequest();
}
}
Then your controller:
public RedirectToRouteResult AddWorkAssignment(int id)
{
// do work to add the work assignment....
return RedirectToAction("Index", "Assignment");
}
[AjaxRequest]
public JsonResult AddWorkAssignment(int id)
{
// do work to add the work assignment....
return Json(true);
}

Related

Get Query String Value in ASP.NET MVC

I have this URL
var url = "/test/Create/" + $("#hdnFlag").val() +"?CmpT="+"Ilim";
window.location.href = url;
and in my Test controller I do this to get query string value
tM_PMO.Type = Request.QueryString["CmpT"];
But always give me null values.
There is a difference between the GET and POST types.
Query string can be read with the URL of the GET request. However, you cannot read the Query string value in the URL when you make a POST request. For this you need to submit it to the server.
Below I give you a few examples of usage.
GET Request
You can read Query string with URL as below
public ActionResult Test(string CmpT)
{
if (!string.IsNullOrWhiteSpace(CmpT))
{
//your codes...
}else
{ }
return View();
}
POST Request
If you are making a POST request and trying to read from the URL, it will return null. In order to read it, you need to send this value to the server as follows.
1st way : In your Html.BeginForm in your View Below, submit Query string as below and read this value as Action parameter
View Page
#using (Html.BeginForm("Test", "XController", new { returnUrl = Request.QueryString["CmpT"] }, FormMethod.Post, new { role = "form" }))
{
<button type="submit">Send</button>
}
Controller
public ActionResult Test(string returnUrl)
{
if (!string.IsNullOrWhiteSpace(returnUrl))
{
//your codes...
}else
{ }
return View();
}
2nd way : Create a hidden form element as part of the form between the Html.BeginForm tags in your view page and give its value as a query string. Then call it in Action method like below.
View Page
#using (Html.BeginForm("Test", "XController", FormMethod.Post, new { role = "form" }))
{
#Html.Hidden("returnUrl", Request.QueryString["CmpT"])
<button type="submit">Send</button>
}
Controller
public ActionResult Test(string returnUrl)
{
if (!string.IsNullOrWhiteSpace(returnUrl))
{
//your codes...
}else
{ }
return View();
}
or for multiple form items (You can also access other form elements this way)
public ActionResult Test(FormCollection fc)
{
string _returnUrl = fc["returnUrl"];
if (!string.IsNullOrWhiteSpace(_returnUrl))
{
//your codes...
}else
{ }
return View();
}
I hope you are looking for below code sample where we just fetch the value in url which we says query string:
Request.QueryString["querystringparamname"].ToString();
You can assign this in any Var and use accordingly.

Load a partial view (or more than one) after data is loaded in another

I have a script that renders a partial view after its data is loaded, but I want at least one other partial view to load using the same data. It's a long-running query (30sec - 1min), so I don't want to load it for each partial view. Or am I going down the wrong path? It should be noted I'm still pretty new to ASP.Net and very new to Javascript/Jquery, so I'm not totally aware of best practices, so if you spot something that's "against convention", please let me know that, too.
EDIT: It dawned on me I should note what I'm trying to eventually get to. In my current non-ASP app (C#/XAML), it loads the data (with an equivalent of LoadMonitorData method, below) when the app loads, then refreshes every 15 minutes. Or the refresh can be triggered by a Refresh button.
Here's what I've got so far...any help or guidance would be greatly appreciated.
Index.cshtml
#{
ViewBag.Title = "MMCView";
}
#section scripts {
<script type="text/javascript">
$(document).on('click', '[name^=project]', function () {
if ($(this).hasClass('selected')) {
$('.mig-project').removeClass('selected').removeClass('low-opacity').addClass('full-opacity');
$('#data-area').removeClass('show-data-view');
}
else {
$(this).addClass("selected").addClass('full-opacity').removeClass('low-opacity');
$('.mig-project').not(this).removeClass("full-opacity").removeClass('selected').addClass("low-opacity");
$('#data-area').load($(this).data("url"));
$('#data-area').addClass('show-data-view');
}
})
</script>
<script type="text/javascript">
$(document).ready(function(e) {
$("#list-container").each(function(index, item) {
var url = $(item).data("url");
if (url && url.length > 0) {
$(item).load(url);
}
})
})
</script>
}
<div class="project-list slow-load" id="list-container" data-url="/mmc/projectpanes">
<img src="loading.gif" />
</div>
<div class="hide-data-view slow-load" id="data-area" data-url="/mmc/projectdata"></div>
MMCController.cs
using MMC_ASP.Models;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using System.Web.Script.Serialization;
namespace MMC_ASP.Controllers
{
public class MMCController : AsyncController
{
MonitorData downloadedInfo = new MonitorData();
//GET: MMC
public ActionResult Index()
{
return View();
}
public ActionResult ProjectPanes()
{
downloadedInfo = LoadMonitorData();
return PartialView("_ProjectPanes", downloadedInfo.MainPanel.OrderBy(o => o.Client).ToList());
}
public ActionResult ProjectData(string server)
{
return PartialView("_ProjectData", downloadedInfo.Information.Where(x => x.ServerName == server).ToList());
}
public ActionResult MainWindowMonitor()
{
return PartialView("_MainWindowMonitor", downloadedInfo.MonitorText);
}
public MonitorData LoadMonitorData()
{
MonitorData deserializedData = null;
using (WebClient wc = new WebClient())
{
wc.Encoding = Encoding.Unicode;
string location = "http://MYWEBAPI-RETURNS-JSON";
string data = wc.DownloadString(new System.Uri(location));
var deserializer = new JavaScriptSerializer();
deserializedData = deserializer.Deserialize<MonitorData>(data);
}
return deserializedData;
}
}
}
In this situation, the Cache object might be useful to you. You can store your data in the Cache, set it to expire after a reasonable amount of time, write a helper function to re-pull the data on the fly if the cached data has expired, and have your partial views pull their data from the helper function. This way, the new data will only be pulled as needed, regardless how many views are using it, and as a bonus you have easy control over how often to re-execute that expensive query.
Note that this works well in your situation because your data is global in nature. If you were passing user-specific parameters into your query, then Cache wouldn't be a good fit.
using System.Web.Caching;
private MonitorData getCachedData()
{
var cache = this.HttpContext.Cache;
if (cache["MonitorData"] == null)
cache.Add("MonitorData", LoadMonitorData(), null, DateTime.Now.AddMinutes(15), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null); // 15 minute cache expiration, as example
return (MonitorData)cache["MonitorData"];
}
public ActionResult ProjectPanes()
{
downloadedInfo = getCachedData();
return PartialView("_ProjectPanes", downloadedInfo.MainPanel.OrderBy(o => o.Client).ToList());
}
public ActionResult ProjectData(string server)
{
downloadedInfo = getCachedData();
return PartialView("_ProjectData", downloadedInfo.Information.Where(x => x.ServerName == server).ToList());
}
public ActionResult MainWindowMonitor()
{
downloadedInfo = getCachedData();
return PartialView("_MainWindowMonitor", downloadedInfo.MonitorText);
}
The solution that Joe_Irby proposed works great! However, while communicating with him I found another approach that works as well. I figured I'd include it here so anyone else looking for a solution can decide which one will be best for their situation.
https://code.msdn.microsoft.com/Caching-In-Web-API-cb40be30

Want to call js method without onclick or onsubmit button of ajax in wicket

I want to call a js method in wicket without using event. For eg, please see below:
public method(Page params) {
Form<?> form = new Form("dataform");
form.add(new AjaxFallbackButton("nextPages", form) {
#Override
public void onSubmit(AjaxRequestTarget target,Form<?> form) {
//do something
}
});
add(form);
}
What I want to achieve is as follow:
public method(Page params) {
Form<?> form = new Form("dataform");
form.add(new AjaxFallbackButton("nextPages", form) {
//do something
});
add(form);
}
I dont want to use setInterval method as I am not sure how much time the user will take to fill the form.
Is there any other way through which I can call the js method?
I did not understand what you want to do exactly, but maybe you can use renderHead method on form creation:
public method(Page params) {
Form<?> form = new Form("dataform"){
#Override
public void renderHead(IHeaderResponse response) {
String js ="your js";
response.render(OnDomReadyHeaderItem.forScript(js));
super.renderHead(response);
}
};
add(form);
}

Auto update a table on button click

I have a table in a page. I want to update / reload the table continuously on a button click for every 5 seconds.
The table gets the values from the query running in the model and I don't want duplicate values to be put in the table again.
I also want to stop the reloading of the table on when I click on a another button which is the stop button.
How can I do it? Thanks!
When you click on first button set interval function, which will execute your updating script. And click on other button will clear this interval.
// Click on first button
var flag = setInterval(func, 5000);
// Click on second button
clearInterval(flag);
where func is your updating function
Try that if possible.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using bhanu1.Models;
namespace bhanu1.Controllers
{
public class ranuController : Controller
{
//
// GET: /ranu/
private personEntities1 per = new personEntities1();
public ActionResult Index()
{
return View(per.sandeep1.ToList());
}
//
// GET: /ranu/Details/5
public ActionResult Details(int id)
{
return View();
}
//
// GET: /ranu/Create
public ActionResult Create()
{
return View();
}
//
// POST: /ranu/Create
[HttpPost]
public ActionResult Create([Bind(Exclude = "Id")]sandeep1 san)
{
try
{
// TODO: Add insert logic here
per.AddTosandeep1(san);
per.SaveChanges();
return RedirectToAction("Index");
}
catch
{
return View();
}
}
//
// GET: /ranu/Edit/5
public ActionResult Edit(int id)
{
return View();
}
//
// POST: /ranu/Edit/5
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
try
{
// TODO: Add update logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
//
// GET: /ranu/Delete/5
public ActionResult Delete(int id)
{
return View();
}
//
// POST: /ranu/Delete/5
[HttpPost]
public ActionResult Delete(int id, FormCollection collection)
{
try
{
// TODO: Add delete logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
}
}

ASP.NET MVC 4 AJAX.BeginForm and PartialViews

I am considering building a SPA using AJAX.BeginForm, however I am facing an issue when a user has JavaScript disabled, instead of redirecting him to _Layout.cshtml + PartialView.cshtml, it redirects him to just the PartialView.cshtml..
Is there a way to include the Layout and the PartialView in it (where it would be if JavaScript was enabled)?
Thanks
Edit:
Awesome.. Thanks.. I managed to get it working but I am not sure it's the best implementation..
[HttpPost]
public ActionResult Index(Newsletter newsletter)
{
if (ModelState.IsValid)
{
db.Newsletters.Add(newsletter);
db.SaveChanges();
ViewData["message"] = "thanks for signing up to our newsletter!";
if (Request.IsAjaxRequest())
{
return PartialView( "SimpleMessage" );
}
}
return View();
}
And SimpleMessage.phtml is simply just #ViewData["message"];
whereas my View.phtml I have got a condition and checks whether ViewBag["message"] is set or not. If it's set, then it means it's a postback and doesn't show the form and shows the message instead, or else it shows the form:
You can check if Action was called via Ajax, or not, and return different type of result
public ActionResult MyAction()
{
if(Request.IsAjaxRequest()) {
// Html fragment
return PartialView();
}
else {
// Complete HTML page
return View();
}
}
If it's postback, you can pass your model, or simple types (int, string) around as well:
[HttpPost]
public ActionResult MyAction(Model model)
{
if(Request.IsAjaxRequest()) {
// Html fragment
return PartialView(model);
}
else {
// Complete HTML page
return View(model);
}
}
Edit: In your specific case I would do like this, but it's only my preference.
[HttpPost]
public ActionResult Index(Newsletter newsletter)
{
if (ModelState.IsValid)
{
db.Newsletters.Add(newsletter);
db.SaveChanges();
if (Request.IsAjaxRequest())
return PartialView("SimpleMessage");
else
return View("SimpleMessage")
}
if (Request.IsAjaxRequest())
return PartialView(newsletter);
else
return View(newsletter);
}

Categories

Resources