I have a situation where a when a web page is accessed a controller action runs which retrieves the data for that page based on a user selection. I am attempting to send the data back to the page as a JSON object, however, the data opens up as one large string in an HTML page. The controller action, in a nutshell, looks like the following snippet:
Public JsonResult MyMethod(string userSelection)
{
string userData = (string) Data;
return Json(userData, “text”, JsonRequestBehavior.AllowGet);
}
I first tried to use the JQuery $.getJson() method but I think this is wrong as I believe it issues another call to the action method for the data, which is not what I want to do. What I want is to access the JSON object in JavaScript code so I can use the property data to populate fields on the web page. The basic question is what must I do in my JavaScript to receive the JSON object when the page is first rendered? I apologize if I am missing something fundamental; this is my first try.
I still had no luck today but when I left work I came up with a strategy walking to my car. A user makes a selection from a page that presents a list prior to entering the page on which I cannot figure out how to work with JsonResult. Part of the problem is the user selection contains a link that calls the controller/action that returns the JsonResult which conflicts with using $.getJson() within the page where I want to work with JsonResult. So here is my strategy: When the user makes the selection that brings them to the (problematic) page, I will call a controller/action that strictly works with (ASP) ViewData, and use the ViewData to initially present that page. Once on the page, the user can change the selection -- I will handle this with a JavaScript event that uses a $.getJason() call to a different controller/action method that works with (ASP) JsonResult. After I try this strategy I shall post my results for whomever is interested.
You want parseJSON not getJSON
http://api.jquery.com/jQuery.parseJSON/
Edit - Oh wait you are pointing your browser at the JsonResult as if it was an ActionResult? That is not going to work.
Render a proper view, and use getJSON to call the JsonResult action.
getJSON is what you are looking for. Call that on the DOM ready event which will executes once the DOM finishes loading.
$(function(){
//This code will be executed on the DOM ready ( when the page is loaded)
$.getJSON("YourControllerName/MyMethod?userSelection=someValue",function(data){
alert(data.FirstName);
alert(data.AnotherPropertyName);
});
});
getJSON is a shorthand of jQuery ajax method with datatype set as json
Assuming your JSON data you are retuning is something like this
{
"FirstName": "Scott",
"AnotherPropertyName": "SomeValue"
}
To return data like above, change your Action method like this
public JsonResult MyMethod(string userSelection)
{
var result=new { FirstName="Scott", AnotherPropertyName="Great"};
return Json(result,JsonRequestBehavior.AllowGet);
}
Related
I'm in the process of getting my head wrapped around using AJAX to update a portion of an MVC View using some conditional logic. I posted the question earlier and was pointed to using PartialView to build out the whole HTML table and then pass that back to the View.
That lead me to use this article and an example.
https://www.red-gate.com/simple-talk/dotnet/asp-net/revisiting-partial-view-rendering-in-asp-net-mvc/
I then pulled out my table code and put it in a Partial View. All that worked just fine. However, now I'm trying to update with AJAX and the actual updating of the database is working but the updating of the View is not.
In other words, when I click on the "Test" button in the code below I can see it going to the HttpPost in the controller as well as seeing the database being updated. However, the page doesn't get updated. I have to refresh the page again to see the change.
I'm betting it has to do with the #Html.Partial call in the View but I'm not figuring out what I need to do to fix it.
From what I've read it sounds as though when I make the AJAX call and it returns the HTML it should replace everything in side of my DIV.
Here is what I have in my View. Upon initially viewing the page the #Html.Partial is populating the table as expected.
<div id="exceptionTable">
#Html.Partial("_DailyLogExceptionsTable", Model.listExceptions)
</div>
Here is my AJAX call. I can see the values coming through. The RID is the record ID and the arg would be a static value of either "A" or "D" depending on which button they will click.
function ApproveDeny(rid, arg) {
var url = "/Exception/ExceptionApproveDeny/";
$.post(url, {rid:rid, arg:arg})
.done(function (response) {
$("#exceptionTable").html(response);
})
};
This is my ActionResult which updates the database through the DAL. Then I create a new ViewModel, call get the new list of Exceptions, and then call the PartialView again passing it the new list of exceptions.
public ActionResult ExceptionApproveDeny(int rid, string arg, string shift)
{
try
{
DAL.ExceptionApproveDeny(rid, arg);
var vm = new ExceptionLogDailyTableViewModel();
vm.listExceptions = DAL.GetEmployeeExceptionsByDate(CurrentEmployeeId, DateTime.Parse(shift));
return PartialView("_DailyLogExceptionsTable", vm);
}
catch (Exception ex)
{
//error code
}
}
I have a view that displays both the search screen and the results list. To start the results list is hidden.
On clicking the search button, instead of the view posting back to the controller using a Html.BeginForm, it has a JavaScript event handler which is called.
The Handler passes over a complex object, in the form of:
{ "searchData":
{ "ticketNumberCompare":0,
"ticketSearchTextFrom":"0",
"ticketSearchTextTo":null,
"ticketDateCompare":1,
"startDate":"2017-01-06T00:00:00",
"endDate":"2017-01-13T00:00:00",
...
etc
...
},
"searchMode":
{ "mode":2,
"pageNumber":1,
"pageSize":5,
"sortDirection":"desc",
...
etc
...
"ValidationErrorMessages":null
}
}
By using Json.Stringify, I have got the above structure to be converted for use by a function within the c# MVC 5 controller, defined as follows.
[HttpPost]
public JsonResult GetSearchResultsJson(ComplexObject searchCriteria, int? page)
{
}
This function returns back html which is rendered from a Razor view using a model that contains the results from the database.
When I click on the submit button for the initial search all works and I get a partial view of five records displayed with the correct pageList values displayed.
When I click on the pageList items I get a page not found error.
On checking the ajax call for the initial load it is passing over the Json.Stringify of the structure at the top of this question. But the pageList items are not, they just pass over the page
Addendum:
Oh I forgot to mention that I have upgraded this function to use an object instead of the four string that used to be passed, because a new super search now has around 30 properties. Before the change the code worked fine.
The first image shows that the method I created in user class.
The second image shows the controller that I created. How I take the data from GetGroupManagerAndFranchiseConsultantList? What should I need to write within view?
Right now you are returning Json. So I assume you are calling this call from something like this
<script>
$.getJSON("/Search",function(data){
// data is a JS OBJECT of your JSON data.
});
</script>
If you were looking to use MVC Views you need to return it as a view and use the built-in model binding.
from my razor edit view I'm hitting mvc controller action where I'm returning ActionResult View.
$.post('/products/details/', { id: someId });
public ActionResult Details(id)
{
...
return View();// in breakpoint this is hitted but never returned as this view.
}
It's always returns me on page where jquery post is initated.
$.post without a callback is like ordering a Pizza then going to bed and forgetting about it. The delivery guy leaves it on the doorstep, where it then gets dragged away by dogs and you never see it :)
Basically: The result of an Ajax post is ignored unless you do something with it.
e.g.
$.post('/products/details/', { id: someId }, function(htmlReturned){
// Do something with the page HTML returned
$('body').html(htmlReturned); // e.g. replace the entire page!
});
I have a Sinatra app which loads information from an external API and displays it on a page. This is done in Sinatra which gets the information and puts it a temporary model instance (which is NOT saved), so it is easier to access all its propertys in the view.
Now when the user clicks a link I want the model instance to be saved to the database, which I think only can be done via AJAX etc. because the last request already finished and none of the instances is still alive. I thought I needed to extract all the information of the corresponding HTML elements and make an AJAX-Post to another route.
My problem is now, I want to be able to create(and save) the model using #model = Model.create(params[:model]). It would be clear what to do using a form, but that is not an option because all the data is displayed within a table and each table row is one instance of the model.
How do I serialize the data from the table row in which the clicked link is, so I can use it as described above?
UPDATE
I am using MULTIPLE instances of the object class, each in one tablerow!
I am using DataMapper, only the temporary objects are not stored!
I dont want to clutter up my whole setup!
Did you consider ActiveResource? You can use ActiveResource to maintain object state. If your REST API follows convention it would be very easy to map resource.
Regarding second half sending back data to your controller, you could store in hidden variable(s) and on post it should be easy to construct back the object and persist it to database.
Something like
#model
class MyModel < ActiveResource::Base
# set configs here
end
# To fetch record from REST API in controller or whatever
MyModel.find(1)
#in controller on form submit or AJAX
post "/path" do
MyModel.new(params[:myModel])
end
Update
To maintain state of object without using hidden form
in javascript you can have something like
var myModel = #{myModel.to_json}; #Ruby interpolation in HAML it will depend on templating language
on certain action you can update the JSON object
and to post using AJAX
$.post("post/path", myModel);
More Update
In External JS
function my_js_function(obj) {
/* do something useful here like setting up object hash etc
*/
}
In Ruby Template
<script>
var myObj = #{myObj.json}
my_js_function(myObj);
</script>
I found a pretty easy solution. It was nothing more than getting all the required values from the DOM and putting them into an Array!
application.js:
$(".enable").click(function() {
var table_row = $(this).closest("tr");
var model_array = new Array;
var elements_with_information = jRow.find("[name]");
elements_with_information.each(function() {
// Doing some checking on which kind of element
// it actually is and then basically doing:
model_array.push($(this).text());
});
// Constructing nested array to use `params[:model]`
var data = { "model" : {
"property1": model_array[0],
"property2": model_array[1]
}};
// Now doing the AJAX request
$.ajax({
url: "/model/doshit",
type: "POST",
data: data
});
});