Using AJAX in a Shared MVC Component - c#

I have AJAX working for a single page, but I want it to work across all pages. How can I accomplish it?
Here is the JavaScript in scripts.cshtml:
function changeTab(tabId) {
var url = "Home/changeTab/" + tabId;
$.ajax({
url: "Home/changeTab/" + tabId,
success: function (tab) {
var t = tab;
$("#menu1").html(t);
}
});
}
I have a component Home.cs:
namespace Web.Controllers
{
public class HomeController : Controller
{
[Authorize]
public ActionResult Index()
{
return View();
}
[AcceptVerbs("GET")]
public JsonResult changeTab(int id)
{
var saveTab = id;
string username = User.Identity.Name;
[...]
return Json(username, JsonRequestBehavior.AllowGet);
}
}
}
The code works well on the Home page, but not on any other. Where do I place the changeTab function so that every page can call it?

try change your script into the following :
function changeTab(tabId) {
var url = '#Url.Action("changeTab", "Home")/' + tabId;
$.ajax({
url: url,
success: function (tab) {
var t = tab;
$("#menu1").html(t);
}
});
}

Related

Ajax call to controller results in 400 error

I have the follow Ajax call that points to a controller function:
<script type="text/javascript">
$(document).ready(function () {
$('#AddNote').click(function () {
$('#AddNote').addClass("disabled");
var txtNote = document.getElementById('note');
var result = document.getElementById('result');
result.innerText = "Adding note...";
$.ajax({
url: "#Url.Action("AddNoteAsync", "Leads")",
type: "POST",
data: { leadId: #Model.Id, note: txtNote.value },
async: true,
success: function (data) {
// removed
},
});
});
});
</script>
When I click the AddNote button I see the "Adding note..." message display and then nothing else happens. When I check the console in chrome, it reads:
:44309/Leads/AddNoteAsync:1 - Failed to load resource: the server responded with a status of 400 ()
So I know 400 means bad request but I'm not sure why it's happening. I've tried:
Added quotes to the "leadId" and "note" field in data - made no difference.
Added alert boxes to show the value of #Model.Id and txtNote.value before the AJAX call to verify they are correct - they are.
Put a breakpoint in the AddNoteAsync function in my controller - it's never hit
Hard coded the url field to /Leads/AddNoteAsync - made no difference
Since the controller function is never being hit I'm assuming something is wrong with the &.ajax part but I cannot figure out what.
Edit: The controller method:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> AddNoteAsync(int? leadId, string note)
{
ViewData["AddedNote"] = false;
if (leadId == null)
{
return RedirectToAction("Index", new { initials = User.Identity.Name });
}
var lead = await _context.Leads.FirstOrDefaultAsync(m => m.Id == leadId);
if (lead == null)
{
return RedirectToAction("Index", new { initials = User.Identity.Name });
}
var ownsLead = await LeadBelongsToCurrentUser(leadId.Value, User.Identity.Name);
if (!ownsLead)
{
return RedirectToAction("Index", new { initials = User.Identity.Name });
}
_context.LeadNotes.Add(new LeadNoteModel()
{
LeadId = leadId.Value,
Note = note,
NoteDate = DateTime.Now
});
await _context.SaveChangesAsync();
ViewData["AddedNote"] = true;
return Content("Success");
}
You should accept parameters as Model while making POST request(Recommended). Proposed Model will be -
public class NoteModel
{
public int? leadId { get; set; }
public string note { get; set; }
}
and Action can be -
public async Task<IActionResult> AddNoteAsync(NoteModel model)
{
}
Also Jquery can be -
<script type="text/javascript">
$(document).ready(function () {
$('#AddNote').click(function () {
$('#AddNote').addClass("disabled");
var txtNote = document.getElementById('note');
var result = document.getElementById('result');
var postData = { leadId: #Model.Id, note: txtNote.value };
result.innerText = "Adding note...";
$.ajax({
url: "#Url.Action("AddNoteAsync", "Leads")",
type: "POST",
data: JSON.stringify(postData),
async: true,
success: function (data) {
// removed
},
});
});
});
Fixed this. I was missing this from my AJAX request:
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="f"]').val());
},
And this from my Startup.cs:
services.AddAntiforgery(options =>
{
options.FormFieldName = "f";
options.HeaderName = "XSRF-TOKEN";
});

MVC 5 AJAX Code is not accessing Controller Class Action Server Side

The intention of the code:
The intention of this code is to accept data passed to it through the scope and place in an array to be passed to a Login controller (Server Side) via AJAX.
The Problem
The AJAX code does not seem as if it is successfully contacting the serverside action.
I have tried moving the action from the login controller to the home controller: No success.
I have tried following the guidelines of those who previously ran into this issue: No success.
I have tried hardcoding the URL to the action: No success.
Below is the AJAX Call:
login: function (username, password) {
var cred = { "uname": username, "pass": password };
var response = $http({
method: "POST",
url: '#(Url.Action("CheckUser","Login"))',
data: JSON.stringify({ model: cred }),
contentType: 'application/json; charset=utf-8',
dataType: "JSON",
success: function (msg) {
if (msg) {
console.log("success: " + msg);
}
},
error: function (msg) {
if (msg) {
console.log("Error:" + msg);
}
},
failure: function (msg) {
if (msg) {
console.log("fail: " + msg);
}
}
});
Next the action code:
namespace test4.Controllers
{
public class LoginController : Controller
{
// GET: Login
public ActionResult Login()
{
return View();
}
public class UserCred
{
public string Uname { get; set; }
public string Pass { get; set; }
}
[HttpPost]
public ActionResult CheckUser(UserCred umodel)
{
Console.WriteLine("I am here");
if (!ModelState.IsValid)
{
return Content("0");
}
string uname = umodel.Uname;
string pword = umodel.Pass;
using (localtestEntities entity = new localtestEntities()) {
var user = entity.users.Where(u => u.uname == uname).FirstOrDefault();
if (user != null) {
if (pword == user.pw) {
Session["LoginID"] = user.id;
Session["Username"] = user.fname + ' ' + user.lname;
return Content(user.id.ToString());
} else {
return Content("0");
}
} else {
return Content("0");
}
}
/* Begin Assigning values */
} //End Check User
}
}
The intended result is to pass back to the client side code whether the comparison of strings passed and what is in the database matches.
A couple things:
$Http({... is not an actual ajax function. I would recommend using $.post() for [HttpPost] and $.get() for [HttpGet]. You can review this in detail from jQuery's documentation here: https://api.jquery.com/jquery.post/
That URL will not work. You can't access razor helper methods inside of JS. As is, you're literally passing #(Url.Action("CheckUser","Login")) into your url so it would look something like localhost:3000/#(Url.Action("CheckUser","Login")) which obviously is not a legit route. You're going to have to get that URL to your ajax function a different way. Some options:
1) In the header of your .cshtml file, do something like:
<script>
$(() => {
const url = `#Url.Action("CheckUser","Login")`;
//Pass that into your JS code via a constructor parameter if your JS
//is a class or by function parameter if your JS code is a function.
const myJSClassNameHere = new myJSClassHere(url);
});
</script>
2) you can just hard code the url into the ajax call. This is a viable option if you don't anticipate the url to change and/or if your standards allow it.

How to send one value after successful ajax post request to a page redirect

I am learning ASP.net MVC - 5 and I am stuck at one problem. So I need to open a URL after successful Ajax Post Request. But I also want to pass one value to the new URL's Controller Action. Below is what I have till now.
AJAX CALL
$.ajax({
url: URL,
type: 'POST',
data: data,
success: function (result) {
if (result == true) {
int TEMPVAR = 2;
DisplayError('Save Successful', 'Success', function () {
window.location.href = '/Settings/Customize/'; });
},
error: function (error) {
}
});
Controller Action
[AuthorizeSettings]
public ActionResult Customize()
{
//I want to be able to access TEMPVAR value here
// code removed for brevity
return View(configData);
}
Question: How to pass the TEMPVAR data to the Customize Action
Points:
I know there are some ways to pass data. TempData,Viewbag,SessionVariable, Embedding the TEMP value in URL Request, Anonymous Objects, ViewData, Static variable for the class, Global Variable, JSON. But I am totally confused how to pass data. I am newbiew please guide me here.
EDIT:
AJAX CALL
$.ajax({
url: URL,
type: 'POST',
data: data,
success: function (result) {
if (result == true) {
int TEMPVAR = 2;
DisplayError('Save Successful', 'Success', function () {
window.location.href = '/Settings/Customize/'; });
TEMPDATA["value"] = TEMPVAR;
},
error: function (error) {
}
});
Based on comments, you want to send data from SaveStyles to Customize. If so, you can use TempData -
public class PersistController : Controller
{
[HttpPost]
public ActionResult SaveStyles()
{
TempData["Status"] = true;
TempData["Val"] = 4;
return Json(true);
}
}
public class SettingsController : Controller
{
public ActionResult Customize()
{
bool status = Convert.ToBoolean(TempData["Status"]);
int val = Convert.ToInt32(TempData["Val"]);
return View();
}
}

Json Object from cshtml to controller using JQuery

I have a jquery function like this.
var jsonArg = new Object();
$(".x").each(function () {
var val1 = "Domain:" + $(this).children(".y").html();
var val2 = "shop:" + $(this).children(".z").html();
jsonArg[val1] = val2;
});
$.ajax({
type: "POST",
url: "/Home/Mappings",
data: { "jsonArg": jsonArg }
})
Now I want to send value of jsonArg to my controller.
My Controller looks like this,
[HttpPost]
public ActionResult Mappings(string Json)
{
return null;
}
I am getting null value in the controller.Please help.
Change variable Name.
[HttpPost]
public ActionResult Mappings(string jsonArg)
{
return null;
}
And Try JSON.stringify();
data: { "jsonArg": JSON.stringify(jsonArg) }

How to pass an object to a MVC controller via Jquery Ajax Get

I am new to jquery and I can't resolve the following problem : I want to pass an object to one of the controllers in my mvc application. Here is what I got so far:
function enterPressed() {
$(function () {
$('#textBox').keypress(function (e) {
var code = e.keyCode ? e.keyCode : e.which;
if (code == 13) {
doSomethingElse(textBox.value)
}
});
});
}
function doSomethingElse(p) {
$.ajax({
type: 'GET',
data: {string: p},
url: '"Control/AddControl/Index"',
success: function (data) { alert(p) },
error: function (errorData) { alert("fail") }
});
return true;
But every time when I press enter I end up with the fail. My controller is found in ~/Controllers/Control/AddControl. Do any of you see the problem ?
My C# code:
public class AddControlController : Controller
{
//
// GET: /AddControl/
public ActionResult Index(string control)
{
return RedirectToAction("ShowControl");
}
}
You should change value name to control, as action expected. Also you can use #Url.Action() helper for setting url param.
$.ajax({
type: 'GET',
data: { control : p},
url: '#Url.Action("Index","AddControl")',
success: function (data) { alert(p) },
error: function (errorData) { alert("fail") }
});
Finally, your action can't return redirect action with ajax response.
If you want to make redirect after successful response, you can make it in client side.
There are a few problems:
1-you are using a wrong url. The correct url is '/AddControl/Index'.
2-Your code in your controller won't work, since you are using ajax. You should return Json and handle the redirect in the client side.
3-You should allow GET through ajax:
public ActionResult Index()
{
return Json("Ok", JsonRequestBehavior.AllowGet);
}
You might want to just POST in stead of GET.
function doSomethingElse(p) {
$.post(
'#Url.Action("Index", "AddControl")',
{
control: p
},
function (data) {
alert(data);
}
);
}
You should decorate your controller action with the HttpPost attribute:
[HttpPost]
public ActionResult Index(string control)
{
return Json("I received this: " + control);
}

Categories

Resources