Strange Behaviour with Ajax - c#

I am working on ASP.net MVC 2.0 Application. I am using Ajax form. In that I have a dropdown and a button.
After clicking on button, i wanted to reload the dropdown if the Ajax request is sucessful.
So, i am calling a jquery Ajax function inside the callback function of the Ajax form.
In that jquery Ajax function, I am writing code to get the new data and binding to drop down so that it will be reloaded with new data.
Here, Every thing is working fine for the first time. But, when i click the button for the next time, the Ajax jquery function is called but it is not hitting contoller action method.
Code:
Here, are my jquery functions:
<script type="text/javascript">
function GetData() {
$.getJSON("/Home/GetUsers", null, function (data) {
var selectList = $("#ddlUsers");
selectList.empty();
alert("Inside Get Json method of jquery Ajax");
var defaultoption = $('<option>').text("--Select--").val("");
selectList.append(defaultoption);
$.each(data, function (index, optionData) {
var option = $('<option>').text(optionData.Text).val(optionData.Value);
alert(option);
selectList.append(option);
});
});
}
function Callback() {
GetData();
alert("Sucessfully done");
}
function Failed() {
alert("Sorry, an error occured while processing your request");
}
Methods inside Contoller:
[HttpGet]
public JsonResult GetUsers() ----> Method that is called from GetData() Ajax call
{
var data = GetUsersList();
return Json(data, JsonRequestBehavior.AllowGet);
}
public SelectList GetUsersList()
{
Db Fectch
return data;
}
I am unable to understand why the above indicated method is not called for second time yet the GetData() is called.
Please help..

I think it's the cache, try adding this line before your controller method:
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
You can also place this line at the top of the controller, if you want it to be applied to all methods.

Related

How to pass jQuery variable value to c# mvc?

How to pass jQuery variable value to c# mvc ?
I need to fetch the value of the variable btn in mvc code behind.
$('button').click(function () {
var btn = $(this).attr('id');
alert(btn);
$.ajax({
type: 'GET',
url: '#Url.Action("ActionName", "ControllerName")',
data: { id: btn },
success: function (result) {
// do something
}
});
});
Based on the variable value (Submit Button (or) Preview Button), my model will have Required validation on certain fields.
In my controller , i am calling as
[HttpGet]
public ActionResult ActionName(string id)
{
var vm = id;
return View(vm);
}
Though , ActionResult in controller is not invoked.
Jquery : alert(btn); -- is calling. I can see the alert window showing with the id. However, I am not able to retrieve the id in the controller.
You need to use jQuery.ajax() (or its shortened form jQuery.get()/jQuery.post()) with GET/POST method and set up a controller action with an argument to pass button ID:
jQuery (inside $(document).ready())
$('button').click(function () {
var btn = $(this).attr('id');
var url = '#Url.Action("ActionName", "ControllerName")';
var data = { id: btn };
// if controller method marked as POST, you need to use '$.post()'
$.get(url, data, function (result) {
// do something
if (result.status == "success") {
window.location = '#Url.Action("AnotherAction", "AnotherController")';
}
});
});
Controller action
[HttpGet]
public ActionResult ActionName(string id)
{
// do something
return Json(new { status = "success", buttonID = id }, JsonRequestBehavior.AllowGet);
}
[HttpGet]
public ActionResult AnotherAction()
{
// do something
return View(model);
}
If you want to pass retrieved button ID from AJAX into other action method, you can utilize TempData or Session to do that.
It is a nice coincidence that you use the word "fetch" to describe what you want to do.
jQuery runs in the browser as a frontend framework. Meaning that it runs on the client`s computer. Your MVC-C#-Code lies on the server. Therefore, if you want to send data between those two computers, you need to use the http protocol.
1. Ajax and REST:
Using an ajax call using http methods (post or put) to push your variable value as JSON to the backend`s REST api (route).
For this option, you might want to have a look at the fetch function of javascript.
2. HTML Forms
Use a html form where you store the variable value inside one input element. A form submission will perform a http post (by default) request to the backend as well and use all input element values as post parameters.
There are many ways to accomplish what you are looking to do, but I'll stick to using your code sample.
So what you need to do is utilize the .ajax call in jquery to send data from your view to your controller. More on that here: http://api.jquery.com/jquery.ajax/
Using your code, you'd put the .ajax call within your logic flow of what to do based on which button is clicked.
$("button").click(function ()
{
var btn = this.id;
if (btn == "previewButton")
{
$.ajax({
url: "/MyApp/MyAction",
type: "POST",
data: { btnId: btn },
dataType: "json",
async: true,
cache: false
}).success(function(data){
// do something here to validate if your handling worked
}).error(function(){
// Do something here if it doesnt work
});
}
}
You'll see that there is a URL. In my example i've chose MyApp as my controller and MyAction as the method of the controller in which we are posting values to. The ajax call posts 1 parameter with a property of btnId. If you need to pass more data, the property name in the jquery call should correspond with an argument of the actions method signature within the controller.
So my controller looks like
public MyAppController : Controller
{
[HttpPost]
public JsonResult MyAction(string btnId)
{
Debug.WriteLine("btnId: {0}", btnId);
return Json(new{ ButtonId= btnId });
}
}
This would be one way to handle passing values from your view to your controller using .ajax calls with jquery.
My preferred way is to use the Html helpers of Ajax.BeginForm which could be another option for you.
https://www.aspsnippets.com/Articles/ASPNet-MVC-AjaxBeginForm-Tutorial-with-example.aspx

How to get selected index changed value in controller mvc c#

I am getting value in a dropdown list and I wanted to get the selected value in controller when user select any value from the dropdown list. My view is -
#using (Html.BeginForm("ApReport", "Sales", FormMethod.Post))
{
#Html.DropDownList("Ddl", null, "All", new { #class = "control-label"})
#Html.Hidden("rddl")
}
controller -
[HttpPost]
public ActionResult ApReport(ApReport Ddl)
{
string Ddlvalue = string.Empty;
if (Request.Form["rddl"] != null)
{
Ddlvalue = Request.Form["rddl"].ToString();
}
}
but I am not getting any value. Also, I donot want to use any submit button.
Thanks in advance
The use of Ajax allows you as the developer to update the main view without reloading the entire page, as well as send data to the server in the background.
This is how I would have accomplished this task.
Firstly, I would have created an action in my controller which returns a JsonResult. This will return a JSON object to your calling jquery code, that you can use to get values back into your views. Here is an example of the action method.
[HttpGet]
public JsonResult YourActionName(string selectedValue) //Assuming key in your dropdown is string
{
var result = DoYourCalculation(selectedValue);
return Json(new { myResult = result }, JsonRequestBehavior.AllowGet);
}
Now, you need to add your jquery code. I would recommend you place this in a seperate javascript file referenced by your view.
Here is the JQuery code, with the ajax call to the Action in your controller. The Ajax call to the server is initiated by the 'change' event of your DropDown, handled in JQuery, as can be seen below.
$(function () {
$(document)
.on('change', '#Ddl', function(){
var valueofDropDown = $(this).val();
var url = '/YourControllerName/YourActionName';
var dataToSend = { selectedValue: valueofDropDown }
$.ajax({
url: url,
data: dataToSend,
type: 'GET',
success: function (dataReceived) {
//update control on View
var receivedValue = dataReceived.myResult ;
$('YourControlIDToUpdate').val(receivedValue);
}
})
});
};

ASP.NET MVC - How to call void controller method without leaving the view?

Question background:
I am implementing some basic 'shopping cart' logic to an MVC app. Currently when I click a link - denoted as 'Add To Cart' on the screen shot below this calls to an 'AddToCart' method in the 'ProductController' as shown:
Product.cshtml code:
#Html.ActionLink("Add To Cart", "AddToCart")
'AddToCart' method in the ProductController:
public void AddToCart()
{
//Logic to add item to the cart.
}
The issue:
Not an issue as such but currently when I click the 'Add To Cart' button on the ActionLink on the ProductDetail.cshtml view the page calls the 'AddToCart' method on the ProductController and gives a blank view on the page - as shown below. I want the view to stay on 'ProductDetail.cshtml' and just call the 'AddToCart' method, how do I do this?
Basically #Html.ActionLink() or <a></a> tag uses get request to locate the page. Hence whenever you clicked it, you request to your AddToCart action method in ProductController and if that action method returns null or void so a blank or empty page is shown as you experienced (because or #Html.ActionLink() get request by Default).
So if you want to add your value to cart then call AddToCart method using ajax i.e:
HTML:
#Html.ActionLink("Add To Cart", "AddToCart", null, new { id="myLink"})
Jquery or Javascript:
$("#myLink").click(function(e){
e.preventDefault();
$.ajax({
url:$(this).attr("href"), // comma here instead of semicolon
success: function(){
alert("Value Added"); // or any other indication if you want to show
}
});
});
'AddToCart' method in the ProductController:
public void AddToCart()
{
//Logic to add item to the cart.
}
Now this time when the call goes to AddToCart method it goes by using ajax hence the whole page will not redirect or change, but its an asynchronous call which execute the AddToCart action method in your ProductController and the current page will remains same. Hence the product will also added to cart and page will not change to blank.
Hope this helps.
The answer of Syed Muhammad Zeeshan is what you are looking for, however you may return an EmptyResult.
public ActionResult AddToCart()
{
//Logic to add item to the cart.
return new EmptyResult();
}
According to this it has no impact on your code ASP.Net MVC Controller Actions that return void
But maybe sometime you want to return data and then you could do something like this:
if (a)
{
return JSon(data);
}
else
{
return new EmptyResult();
}
As many people mentioned here you will need to use AJAX if your using asp.net MVC to hit a controller POST function without having to leave your view.
A good use case for this is if you want to upload a file without refreshing the page and save that on the server.
All of the
return new EmptyResult();
Wont work, they will still redirect you.
Here is how you do it, in your view have the follow form as an example:
<form enctype="multipart/form-data" id="my-form">
<p>
The CSV you want to upload:
</p>
<input type="file" class="file-upload" name="FileUpload" />
</div>
<div>
<button type="submit" class="btn btn-default" name="Submit" value="Upload">Upload</button>
</div>
</form>
Then in the JavaScript side you need to add this to your view with within Script tags.
$("#my-form").on('submit', function (event) {
event.preventDefault();
// create form data
var formData = new FormData();
//grab the file that was provided by the user
var file = $('.file-upload')[0].files[0];
// Loop through each of the selected files.
formData.append('file', file);
if (file) {
// Perform the ajax post
$.ajax({
url: '/YourController/UploadCsv',
data: formData,
processData: false,
contentType: false,
type: 'POST',
success: function (data) {
alert(data);
}
});
}
});
Your controller might look something like this to process this type of file:
[HttpPost]
public void UploadCsv()
{
var listOfObjects = new List<ObjectModel>();
var FileUpload = Request.Files[0]; //Uploaded file
//check we have a file
if (FileUpload.ContentLength > 0)
{
//Workout our file path
string fileName = Path.GetFileName(FileUpload.FileName);
string path = Path.Combine(Server.MapPath("~/App_Data/"), fileName);
//Try and upload
try
{
//save the file
FileUpload.SaveAs(path);
var sr = new StreamReader(FileUpload.InputStream);
string csvData = sr.ReadToEnd();
foreach (string r in csvData.Split('\n').Skip(1))
{
var row = r;
if (!string.IsNullOrEmpty(row))
{
//do something with your data
var dataArray = row.Split(',');
}
}
}
catch (Exception ex)
{
//Catch errors
//log an error
}
}
else
{
//log an error
}
}
There are many ways to accomplish what you want, but some of them require a lot more advanced knowledge of things like JavaScript than you seem aware of.
When you write ASP.NET MVC applications, you are required to have more intimate knowledge of how browsers interact with the web server. This happens over a protocol called HTTP. It's a simple protocol on the surface, but it has many subtle details that you need to understand to successfully write ASP.NET MVC apps. You also need to know more about Html, CSS, and JavaScript.
In your case, you are creating an anchor tag (<a href="..."/>), which when click upon, instructs the browser to navigate to the url in the href. That is why you get a different page.
If you don't want that, there are a number of ways change your application. The first would be, instead of using an ActionLink, you instead simply have a form and post values back to your current controller. And call your "add to cart" code from your post action method.
Another way would be have your AddToCart method look at the referrer header (again, part of that more subtle knowledge of http) and redirect back to that page after it has processed its work.
Yet another way would be to use Ajax, as suggested by Syed, in which data is sent to your controller asynchronously by the browser. This requires that you learn more about JavaScript.
Another option is to use an embedded iframe and have your "add to cart" be it's own page within that iframe. I wouldn't necessarily suggest that approach, but it's a possibility.
Controller should return ActionResult. In this case a redirect to the caller page.
using System.Web.Mvc;
using System.Web.Mvc.Html;
public ActionResult Index()
{
HtmlHelper helper = new HtmlHelper(new ViewContext(ControllerContext, new WebFormView(ControllerContext, "Index"), new ViewDataDictionary(), new TempDataDictionary(), new System.IO.StringWriter()), new ViewPage());
helper.RenderAction("Index2");
return View();
}
public void Index2(/*your arg*/)
{
//your code
}
I was struggling with this and couldn't get it working with ajax.
Eventually got a working solution by making my controller method return type ActionResult rather than void and returning a RedirectToAction() and inputting the action relating to the view I wanted to remain on when calling the controller method.
public ActionResult Method()
{
// logic
return RedirectToAction("ActionName");
}

Redirecting to view page from action in c#

I am using ajax $.post call to redirect to action which is Index, from Index I need to call its View Page, while debugging its going to view page ,but I cant see the same in browser. Here is my ajax code and action code:
AJAX code:
$("#btnSearch").click(function () {
var val=$('#whereSearch').val();
$.post("Search/Index/",{where:val});
});
ACTION Code:
public ActionResult Index(string where)
{
var q = searchQuery(where);
ViewBag.val = q;
return View();
}
Why are you using AJAX for this? You'll get your view passed back as data, you won't get a redirect. Just do this:
$("#btnSearch").click(function (e) {
e.preventDefault();
var val=$('#whereSearch').val();
window.location = "Search/Index/" + val;
});

MVC call method on click with / without postback

I have a question regarding the calling method from view.
Basically on my view I have 2 links:
1 link : When I click on it, some method should be called and executed, but nothing should change on webpage, so no postback.
2 link: When I click on it, some method should happen and postback can happen, on the same page
In controller I have:
public ActionResult FirstMethod(){ return View();}
public ActionResult SecondMethod(){ return View();}
In view:
#Html.ActionLink("Action 1", "FirstMethod", "Controller");
#Html.ActionLink("Action 2", "SecondMethod", "Controller");
So when I click on both action happens but then i get an error saying cannot find FirstMethod.chtml ..
So is this possible to have one method with postback and another one without? And how to return to the same page ... and not try to get FirstMethod.chtml ..
Following solution is based on AJAX -
Controller -
public class DemoController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpGet]
public ActionResult CallMe()
{
return new ContentResult() { Content = "This is Demo " };
}
}
Index.cshtml -
<h2>Index</h2>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script type="text/javascript">
$(function () {
$("#Click").click(function () {
$.ajax({
url: "/Demo/CallMe",
type: "GET",
error: function (response) {
alert(response);
},
success: function (response) {
alert(response);
}
});
});
})
</script>
<input type="button" value="Click" id="Click" />
First navigate to /demo/Index, that will display the page with above markup with a button in the page. And when we click on the Click button, we have -
The #Html.ActionLink method basically just forwards you to the specified controller-action, you cannot change this, since this is the purpose of the method.
You have to handle the click client-side, and bind a specific action to it (post some data to a url, and do nothing afterwards). One fairly easy way to do this, is to use jQuery.Post
Example from the above jquery link.
Example: Request the test.php page, but ignore the return results.
$.post("test.php");
Actually, there is no postback concept in asp.net mvc. all interactions with server should via the controller/action.
#Html.ActionLink() method just generate a link(tag a in html) and do nothing. everything happens after you send a request(such as click the link) to controller/action, if you want do nothing when click the link, you'd better use AJAX method like this
#Html.ActionLink("Action 1", "FirstMethod", "Controller", null/*routeValues*/, new { id = "link1Id" });
<script type="text/javascript">
$(function () {
$("#link1Id").click(function () {
$.get("/Contoller/FirstMethod", function () {
//do nothing or alert(something)
});
return false;
});
})
</script>
You can simply return another view after you've done what you wanted in your controller action:
public ActionResult SecondMethod()
{
//do something
return View("FirstMethod");
}
After you've seen this you will most probably be disgusted by the use of magic strings to reference views or controllers and that disgust is completely understandable :)
Then you should look whether something like T4MVC could fit your needs.

Categories

Resources