How to get variables from JavaScript to ASP.NET (MVC) - c#

I'm using ASP.NET MVC (I'm really new to both asp.net and the asp.net mvc type projects, but trying hard to learn).
I've set up MVC with a controller so that it runs a C#.net method which;
queries an mssql db
converts it to json
returns the json string
It's called from the javascript by requesting an url with a parameter. But what I need now is for the C# part to read two integer variables from the javascript. What would be the best way to do that, and does anyone have any good examples/code that I could look at?
It would be extremely helpful. Especially if there are smart ways of doing it with jquery / asp.net (mvc)

In your controller:
public JsonResult GetPony(string Name, string Color) {
return Json(new Pony(Name, Color), JsonRequestBehavior.AllowGet);
}
In your javascript:
$.get("/Controller/GetPony", {
Name: "foo",
Color: "bar"
});
jQuery will take care of moving stuff from the object into the querystring and MVC will take care of moving stuff from the query string into the call to your action.

To do that you need to send it as part of the ajax request. C# can't read your javascript, it can only read the request parameters.
If you're using jQuery, a request might look like this:
$.ajax({
url:"/products/detail",
type: "get", (or post, etc)
dataType: "json",
data: {productId: 55, culture:"en-US"},
success: your_success_callback,
error: function(e) { alert("An error occurred! " + e); }
});
The line that is interesting there is the data setting. It will serialize the data into name=val&name=val and send it to the server. If the type is set to GET then that will be appended to the querystring on the URL. If it's set to POST, then it will be embedded as part of the request.
The server portion doesn't care which. It can retrieve it like this:
public class ProductsController : Controller
{
public ActionResult Detail(int productId, string culture)
{
//your logic here
}
}

Related

Access code behind from ajax in asp.core 2.0

so I need to implement facebook authentication in asp.net core 2.0 mvc, which I already did. But then I need to access the code behind to perform database actions. I've done that before in classic asp.net but now in core I'm not so sure. I've implemented it before with an ajax function calling a web method function from code behind. Here, in mvc at least, the cs page is separate from the cshtml page. Is it still possible to do it?
Here's my code from the classic asp.net version:
// Client ajax function
function Ajax(expression1, expression2) {
var request = { email: expression1, name: expression2}
$.ajax({
url: 'login.aspx/Login',
method: 'post',
contentType: 'application/json',
data: JSON.stringify(request),
dataType: 'json',
success: function (resp) {
window.location.href = resp.d;
},
error: function () {
}
})
}
// Server side function that I needed to access
[WebMethod]
public static string Login(string email, string name)
{
// Make required validations
return whatever;
}
So now I have the same but in the asp.net core 2.0 mvc way.
Ok, I solved it. So, I have to put, in the url, the name of the controller, which in my case is 'Home', and the name of the method. In this case, it would be: 'Home/Login'. And in the code behind you can have just any function and it will work. But you have to receive the data to an object and the the tag (?) [FromBody] for it to work. For instance:
public string Login([FromBody]User user)
{
}
Yet, if there's an even better way I'm all ears. Thanks, anyway.

Why is my JQuery function POSTing a null JSON string to my controller?

When my JQuery function executes, I'm writing the global variable out to the console to make sure that there's something in it. There is: 24 JSON objects.
Yet, when the function tries to POST this global variable back to the server, the method is getting a null JSON object instead of the 24 items that I'm looking for.
Here's the JQuery function:
$("#dismissBtn").on('click', function()
{
console.log(attendeeClassesGlobal);
alert("Check the console");
// Dismiss button has been clicked, so let's deal
// with the classes for this attendee
$.ajax({
url: "/Class/DismissAttendeeFromAllClasses/",
type: "POST",
data: { attendeeClassesGlobal, __RequestVerificationToken: $('input[name=__RequestVerificationToken]').val() },
dataType: "json",
success: function (attendeeClasses) {
},
error: function (xhr, ajaxOptions, thrownError) {
if (xhr.responseText !== "") {
alertify.alert(xhr.responseText);
alertify.error(xhr.responseText);
}
}
});
});
I've got a breakpoint set in the controller's method that this function is calling. When I check the incoming JSON parameter, it's null. What I can't understand is why the global variable has 24 objects in it inside the JQuery function, but null is being passed. Here's my C# method that handles the POST:
public ActionResult DismissAttendeeFromAllClasses(string json)
{
if (!Employee.CurrentUser.CanEditAttendees)
{
throw new ArgumentException("You are not authorized to perform this action");
}
var attendeeClasses = JsonConvert.DeserializeObject<IList<AttendeeClassViewModel>>(json);
foreach (var attendeeClass in attendeeClasses)
{
Console.WriteLine(attendeeClass);
}
return this.Json(null);
}
So, I'm guessing the way I'm sending the JSON obect to the POST handler is wrong. I'm hoping someone can point out what I'm doing wrong here.
EDIT: Thank you, everyone, for your suggestions. I've tried them all to no avail. Just for reference, this is what my the global variable looks like when I log it to the console in dev tools. There are 24 objects within this array:
I can't see anything wrong with it, but maybe I'm missing something?
EDIT#2: I forgot to mention that even the JSON.stringify didn't help. While it made my JSON objects look nice in the console, they never make it to my controller method because the string json is always null instead of filled with my 24 JSON objects that I'm expecting.
EDIT#3: It appears that I didn't have matching parameter names. Being new to ajax/mvc POSTing, I wasn't aware of this requirement. This resolved my issue. Thanks to all that offered advice!
Why you don't define the parameter in your controller as an object and let the serializer maps the object instead of sending a string?
public ActionResult DismissAttendeeFromAllClasses(IEnumerable<MyViewModel> json)
{
//Do stuff
}
Edit:
As you are sending a collection, you should update your controller accordingly.
Also include contentType: "application/json; charset=utf-8" in the request
The parameter name in the JQuery post function doesn't match the parameter name in the controller method. Once this was fixed, the issue was resolved.

Load a Partial View using jQuery .load() and no Razor

I have a View which is the container for a PartialView. Let's say a Customer - Orders relation. The View should received a CustomerViewModel whereas the PartialView a collection of Orders, such as IEnumerable<OrderViewModel>.
I basically have two ways of doing this (not to mention Angular), either Razor or jQuery. With Razor was pretty straightforward by utilizing #Html.Partial("_CustomerOrdersPartial", Model.Orders). But let's assume I cannot use Razor syntax and here it is how I ended up posting this question. I have read many posts on this matter but, most of them (not to mention all), suggest to use $("#container").load('#Url.Action("ActionName", new { parameterX = valueY })). Then here are my questions:
Why to mix Razor and jQuery?
Is this the only way?
Is there any way to call the View and pass the model?
The last question has to do with the fact that the above code requires an action on the server-side to be called, whereas the #Html.Partial("_CustomerOrdersPartial", Model.Orders) mentioned above will just call the View (client-side) and send the given Model in.
Any idea on how to solve this would be really helpful.
Thanks in advance for your time and thoughts.
my solution is:
function ReturnPanel(div, panel) {
$.ajax({
type: "POST",
url: "#Url.Action("GetPanel", "ControllerName")",
data: JSON.stringify({ 'idCurso': idCurso, 'panel': panel }),
contentType: 'application/json; charset=utf-8',
success: function (response) {
$("#" + div).html(response);
},
error: function (xhr, status, errorThrown) {
//Here the status code can be retrieved like;
alert("Error: status = " + xhr.status + " Descripcion =" + xhr.responseText);
}
})
}
in cs.
[HttpPost]
public ActionResult GetPanel(int idCurso, string panel)
{
Contenido contenido = new Contenido();
contenido.IdCurso = idCurso;
return PartialView(panel, contenido);
}
This code should do it. The trick is to acquire the URL and then make sure you get the parameter list right. I used a little Razor to get the URL but you don't have to. Also, If you fail to match the parameter list, your call will not even be acknowledged. You have been warned. I tried to name every thing in a way that helps.
var url = '/controllerName/ActionName';
$('#pnlFillMee').load(url, {NameOfParam: $('#elementID').val() },
function () {CallMeAfterLoadComplete(); });
Here's a real world example I use at work. ReviewInfo is an action in the
controller associated with this page. It returns a partialview result.
$(document).ready(function () {
var url = '/supervisor/reviewinfo';
$('#pnlReviewInfo').load(url, { FCUName: $('#FCU').children(':selected').text(), AccountsFromDate: $('#AccountsFrom').val()}, function () {
InitializeTabs(true);
});
});
This goes somewhere on your form.
<div id="pnlReviewInfo" style="width: 85%"></div>
EDIT:
I would also look up the other jQuery functions like $.get, $.post and $.ajax which are more specialized versions of $.load. and see this link which might answer all your questions about passing models:
Pass Model To Controller using Jquery/Ajax
Hope this helps
wrapping up this question and thanks to #stephen-muecke and #charles-mcintosh for their help:
Using #Html.Partial(partialViewName) the server returns a string resulting from the partial view passed in. Preferred method if you need to manipulate the partial before being displayed. Otherwise, using #Html.RenderPartial(partialViewName) will write into the stream output sent to the browser, the HTML code from the given partial.
As per jQuery API, $(elem).load(url[,data][,complete]) will place the returned HTML into the matching element. Thus, it requires an action method for the given url.
If for whatever reason Razor cannot be used on the UI, chances are you would likely end up either hard-coding the url like in the sample code provided above by #charles-mcintosh or using Angular.

Download a File by POST (HttpPost action) on ASP.NET MVC controller action using Javascript

Initially, my controller action accepts GET. When my data grew, I was forced to move to POST method to be able to send larger data.
My controller action is as follows:
[HttpPost]
public ActionResult ClausesPdf(MyArrayModel obj)
{
...
return File(pdf, "application/pdf", "file.pdf");
}
How can I call this action and download the file using javascript?
Update: I realized that my original answer about AJAX was not entirely accurate since there is no way to return a file from an AJAX call. I suggest that you look at this SO question: Download Excel file via AJAX MVC. I believe #CSL has a good answer that is similar to what you want.
My answer is not plain javascript. This is an AJAX call in jQuery on how it could be done there:
$.ajax({
url: urlControllerAction,
type: 'POST',
cache: false,
data: //your parameter data here
})
.done(
function(result, textStatus, jqXHR) {
//do something with the "result"
}
)
.fail(
//what should be done if something goes wrong
);

Help with using jQuery with ASP.NET MVC

My app has a "Show all comments" similar to the one in Facebook. When the user clicks on the "show all" link, I need to update my list which initially has upto 4 comments with all comments. I'll show some code first and then ask some questions:
jQuery:
ShowAllComments = function (threadId) {
$.ajax({
type: "POST",
url: "/Home/GetComments",
data: { 'threadId': threadId },
dataType: "json",
success: function (result) {
alert(result);
},
error: function (error) {
alert(error);
}
});
};
Home Controller:
// GET: /GetComments
[HttpPost]
public JsonResult GetComments(int threadId)
{
var comments = repository.GetComments(threadId).ToList();
return Json(comments );
}
Questions:
When I tried GET instead of POST, I got this error: "This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet." Is POST usually recommended instead of GET when making these ajax requests? If not, how do I get it to work with GET? Where do I set JsonRequestBehavior to AllowGet?
After changing it to POST, I now get this error: A circular reference was detected while serializing an object of type 'Models.Thread'. I'm using Entity Framework 4, and I've read that adding a [scriptignore] attribute on the navigation property would resolve this, so I added a partial class of the entity with the property, it said "property is already defined". How do I then deal with this because I can't directly modify the code generated by EF4.
Set in the return Json. I would just use post, but if you want to make it hard on your self, use get.
public JsonResult blah()
{
return Json("obj", JsonRequestBehavior.AllowGet);
}
It is true when most ORM objects get serialized the serialization tries to searlize the hidden goodies the ORM needs, AND (sounds like your case) all of the lazy load stuff... this causes bad mojo. Can I throw a suggestion out? Why not let MVC do what its good at and generate the view for you? You could just use the jQuery .load and use a view.
Answers:
try return Json(comments, JsonRequestBehavior.AllowGet); There are good reasons for the default behavior though.
for anything going down the wire, you are going to really want to create a very simple view model object rather than sending your domain entity down the wire. Lots of fancy things happen in the EntityFramework that don't work with serialization as you are finding out.

Categories