ASP.NET MVC Show View after Ajax call to a Controller - html

I have a View with a submit form: when I click it a jquery/ajax function is called. This function has to encode the View Model, call a Controller action and show the View returned.
Now, this is my function:
<script type="text/javascript">
function Analyze() {
var urlact = '#Url.Action("Analysis")';
var model = '#Html.Raw(Json.Encode(Model))';
$.ajax({
data: model,
type: "POST",
url: urlact,
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (data) {
//WHAT HERE??
}
});
}
</script>
And the Analysis action is a kind of
public ViewResult Analysis(IEnumerable<Azienda> aziende) {
Debug.WriteLine(aziende.Count());
return View(aziende);
}
Returning a View!
How can I display that View on success:function(data)?
I tried changing dataType to html and calling on success alert(data) but I had problems with the encoded model, I tried commenting the contentType line but same model-encoding issue.
Does someone know how to do that?
A js/query/ajax workaround-trick is fine, too.
Thanks you all!

Use
return PartialView()
instead of
return View()
in your controller. Then in the success function in your ajax call, use the jQuery .html() function to update the element you wish to update in your html. See Query.html() and View() vs. PartialView()

Create a separate partial view with aziende as its model and return this in your Analysis action and then append the result to a div in your view:
//action returning a partial view
public ActionResult Analysis(IEnumerable<Azienda> aziende)
{
Debug.WriteLine(aziende.Count());
return PartialView("_partialView", aziende);
}
//then append the result to a div in your javascript
success: function (data) {
$("#some-div").html(data);
}

Related

AJAX/JSON MVC method not being called

The MVC controller method is not being called with the following code and the issue isn't clear. $("#screeners").val() returns a list of strings:
<script>
$(document).ready(function () {
$("#submitScreeners").click(function () {
var selected = $("#screeners").val();
$.ajax({
contentType: 'application/json; charset=utf-8',
dataType: 'json',
type: 'POST',
url: '/Applicant/PassScreeners',
data: "selected=" + JSON.stringify(selected),
success: function () {
$('#result').html('"PassScreeners()" successfully called.');
},
failure: function (response) {
$('#result').html(response);
}
});
});
});
</script>
Method in controller:
public void PassScreeners(List<string> selected)
{
Session["SelectedApplicants"] = selected.Select(e => Int32.Parse(e.ToString())).ToList();
}
If I understand you correctly, the "selected" parameter is being passed in as a null value. I believe this is because you are using an incorrect data format. You tell the server to expect JSON formatted data, but then pass it something more akin to a form value with '='.
Try removing the "selected=" bit from your data line and just pass the stringified list.
If that doesn't work, check the trace and post it. If the string you are posting is just comma separated or something it needs to be an array in order for the POST to work correctly.
Apologies if I've misunderstood.

MVC5 action that can return either View(model) or json

I have a following problem:
I got an EDIT page, it contains some inputs and so on - nothing unusual. On submit button click I have to validate the form on server and do one of the following actions:
return the model if there are errors
return some info saying it's all good
Why? Because I need to display a bootstrap modal window when everything's ok. So what I did is (simplifying):
[HttpPost]
public ActionResult EditData(DataViewModel model)
{
...
if(!ModelState.IsValid)
return View(model);
return Json(new { success = true, message = "all good" }, JsonRequestBehavior.AllowGet);
}
What is the problem? I'm posting the form with javascript and waiting for the answer like that:
{
$(document).on('click', '#submitButton', function () {
$.ajax({
dataType: "json",
url: "/Controller/EditData",
type: "POST",
data: $('#submitForm').serialize()
}).done(function (data) {
console.log(data.success + ' ' + data.message);
if (data.success) {
$('#modalBody').text(data.message);
$('#modal-window-add').modal('show');
}
});
});
}
So as you can see it does display the modal window but it doesn't do anything when a model comes in. In the latter situation completely nothing happens although the response comes.
Is there any other option to solve my problem? Generally I HAVE to display that modal window on successful edit and on modal closing I need to redirect to another page - this is easy. I tried including the model inside the json but it didn't work and it seems like a lot of work to check all the fields manually and then displaying these red errors under inputs that didn't pass validation. I discussed it with my experienced friends but they don't have any MVC based solution. Any idea?
Best regards,
Daniel
User Ajax For to do that work
#{
var ajaxOptions = new AjaxOptions { HttpMethod = "Post", UpdateTargetId = "modal", OnBegin = "onAjaxBegin", OnComplete = "OnAjaxComplete", OnSuccess = "OnAjaxSuccess" };
}
#using (Ajax.BeginForm("Controler", "EditData", ajaxOptions, new { enctype = "multipart/form-data" }))
{
//write html here with model values
}
COntroller Method
[HttpPost]
public ActionResult EditData(DataViewModel model)
{
if(!ModelState.IsValid)
return View(model);
}
Javascript
function OnAjaxSuccess()
{
show hide model popup
}
$.ajax have a dataType option (The type of data that you're expecting back from the server.)
In $.ajax function you added option dataType: "json" that means you expected json back from server so you will get only json not other dataType like xml, html, text, script
In your case you want to return json or html depending on model is valid or not for that you can remove dateType option from $.ajax function, because If none is specified, jQuery will try to infer it based on the MIME type of the response (an XML MIME type will yield XML, in 1.4 JSON will yield a JavaScript object, in 1.4 script will execute the script, and anything else will be returned as a string).

Append additional HTML result in calling MVC action by Ajax in DNN8

I'm new in DNN development.
I have created a very simple module in Visual studio--- A textbox and a button.
I just want to call the action in a controller by click the button, then show the return result in the textbox.
The code call the action success, but not sure why append lots of HTML inforation in the result.
Here is the action in the controller:
public ActionResult test1()
{
return Content("Return something");
}
Here is the Ajax code from the View:
$(document).ready(function () {
$("#btnSub").click(function () {
//alert(this.action);
$.ajax({
type:"GET",
contentType:"application/text",
url: "#Url.Action("test1", "Sky")",
data:"",
dataType: "text",
success: function (data) { $("#txtResult").val(data); alert("Success!") },
error:function(){alert("Failed!")}
});
});
});
And here is the result show in the textbox:
Anyone can let me know why the HTML information returned? Actually, I don't need it.
Thanks
Unfortunately, as described in DNN8 MVC unsupported features, it's not yet possible to return a JsonResult. So the solution I used is to return an ActionResult (although the function returns Json):
public ActionResult Test()
{
return Json(new { success = true });
}
On jquery side, I setup ajax call to receive result as html. This avoid the browser to display a parsing error. Finally, just need to remove the html part and manually parse the response. It's not very clean, but the only solution I found until DNN support JsonResult.
$.ajax({
url: '#Url.Action("Index", "Contact")',
type: 'POST',
dataType: 'html',
data: $('#contact-form input').serialize(),
success: function (response) {
jsonPart = response.substring(0, response.indexOf("<!DOCTYPE html>"));
var data = JSON.parse(jsonPart);
if (data.success) {
alert("Great");
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert("Error!");
}
});
EDIT : Improved solution
DNN8 now support IMvcRouteMapper. You can then register a route in RouteConfig.cs. Once done, you can call the function using following URL :
/DesktopModules/MVC/ModuleName/Controller/Action
The action can return a JsonResult. But pay attention, if you just call that function, it will fail with a null exception on ModuleContext. You have to include in the ajax call the following header :
headers: {
"ModuleId": #Dnn.ModuleContext.ModuleId,
"TabId": #Dnn.ModuleContext.TabId,
"RequestVerificationToken": $("input[name='__RequestVerificationToken']").val()
}
You can find the module complete code here.
This is a working ajax call in DNN 9. You dont have to use #urlaction it will give whole html as well as data. dnn.getVar("sf_siteRoot", "/") +
"DesktopModules/MVC/ModuleName/Controller/Action", this does the trick and don't forget to add the header otherwise it will throw 500 error.
$.ajax({
url: dnn.getVar("sf_siteRoot", "/") +
"DesktopModules/MVC/ModuleName/Controller/Action",
type: 'POST',
contentType: "application/json; charset=utf-8",
dataType: 'json',
data: "{ 'id':" + JSON.stringify(3543)+" }",
headers: {
"ModuleId": #Dnn.ModuleContext.ModuleId,
"TabId": #Dnn.ModuleCon`enter code here`text.TabId,
"RequestVerificationToken":
$("input[name='__RequestVerificationToken']").val()
},
success: function (response) {
debugger;
},
error: function (errmsg) {
alert("Error!");
}
});
Your controller should be
[HttpPost]
public ActionResult ActionName(int id)
{
var data = id;
return BuidJsonResult(true,data);
}
Happy Coding :)

Pass ViewModal from javascript file to code-behind

I have a Javascript file that calls a method in my code-behind. This seems to work if I create a parameterless default constructor, EXAMPLE 1, BUT I want to pass to the save method my ViewModel, EXAMPLE 2. When I do this I get a 500 error. After digging deeper I discovered more details about that network error.
Parameterless Default Constructor - this works but only if the other constructor is commented out.
EXAMPLE 1
[HttpPost]
public JsonResult SaveWorkRequestDetails()
{
return Json(new {});
}
If I have both of these in the code-behind file then I get this error: The current request for action 'SaveWorkRequestDetails' on controller type 'WorkRequestController' is ambiguous between the following action methods:
System.Web.Mvc.JsonResult SaveWorkRequestDetails() on type WorkRequest.Controllers.WorkRequestController
System.Web.Mvc.JsonResult SaveWorkRequestDetails(WorkRequest.ViewModel.WorkRequestViewModel) on type WorkRequest.Controllers.WorkRequestController
EXAMPLE 2
[HttpPost]
public JsonResult SaveWorkRequestDetails(WorkRequestViewModel viewModel)
{
// TODO: Save logic goes here
return Json(new { });
}
I need to pass the viewModel in order to save the user's selections. I am missing something and I am not sure what.
RegisterUIEventHandlers: function () {
$('#Save').click(function (e) {
// Check whether the form is valid. Note: Remove this check, if you are not using HTML5
if (document.forms[0].checkValidity()) {
e.preventDefault();
$.ajax({
type: "POST",
url: WorkRequest.SaveUrl,
data: ko.toJSON(WorkRequest.ViewModel),
contentType: 'application/json',
async: true,
beforeSend: function () {
// Display loading image
alert(ko.toJSON(WorkRequest.ViewModel));
},
success: function (result) {
// Handle the response here.
},
complete: function () {
// Hide loading image.
},
error: function (jqXHR, textStatus, errorThrown) {
// Handle error.
}
});
}
});
}
In the alert you see in beforeSend, in the AJAX POST within the javascript above, I see the selections the user makes. Everything works so I just want to pass this to the Controller's SaveWorkRequestDetails, how can I do this please. I was my understanding that the data parameter passed this on to the method specified in the url parameter.
The error message is clear. You have two action methods with the same name. So, call to the SaveWorkRequestDetails is ambigious as the error indicates.
You can overload functions in C# but it is not possible in ASP.NET MVC Framework.
It is not possible to have two SaveWorkRequestDetails() actions with different method signatures on the same controller in ASP.NET MVC.
Just remove the first SaveWorkRequestDetails(), and you will be fine.
I changed the dataType to json instead of application/json. This resolved the issue of the error stating there was not a parameterless default constructor. Now SaveWorkRequestDetails is being called.
RegisterUIEventHandlers: function () {
$('#Save').click(function (e) {
// Check whether the form is valid. Note: Remove this check, if you are not using HTML5
if (document.forms[0].checkValidity()) {
e.preventDefault();
$.ajax({
type: "POST",
url: WorkRequest.SaveUrl,
data: ko.toJSON(WorkRequest.ViewModel),
dataType: 'json',
async: true,
beforeSend: function () {
// Display loading image
alert(ko.toJSON(WorkRequest.ViewModel));
},
success: function (result) {
// Handle the response here.
},
complete: function () {
// Hide loading image.
},
error: function (jqXHR, textStatus, errorThrown) {
// Handle error.
}
});
}
});

viewbag data is empty in $.ajax

Iam using asp.net mvc4 and facing some problem in accessing viewbag.price.
This is what i am doing:-
[HttpPost]
public ActionResult FillModel(int id)
{
var vehModel = db.Vehicle_Model.Where(vehMod => vehMod.MakeID == id).ToList().Select(vehMod => new SelectListItem() { Text = vehMod.Model, Value = vehMod.pkfModelID.ToString() });
ViewBag.Price = 100;
return Json(vehModel, JsonRequestBehavior.AllowGet);
}
i am calling above using below:-
$.ajax({
url: '#Url.Action("FillModel","Waranty")',
type: 'post',
data: { id: id },
dataType: 'json',
success: function (data) {
$('#ddModel').empty();
$.each(data, function (index, val) {
var optionTag = $('<option></option>');
$(optionTag).val(val.Value).text(val.Text);
$('#ddModel').append(optionTag);
});
var a = '#ViewBag.Price';
},
error: function () {
alert('Error');
}
});
But i am not able to access ViewBag.Price.
Anyone know the reason??
thanks
The reason you aren't able to access items from the ViewBag inside your ajax success function is because the view that contains your script has already been rendered by the Razor view engine, effectively setting the variable a to whatever the value of #ViewBag.Price was at the time the page was rendered.
Looking at the process flow might be helpful:
(1) The request comes in for the view that has your script fragment in it.
(2) The controller method that returns your view is called.
(3) The Razor view engine goes through the view and replaces any references to #ViewBag.Price in your view with the actual value of ViewBag.Price. Assuming ViewBag.Price doesn't have a value yet, the success function in your script is now
success: function (data) {
$('#ddModel').empty();
$.each(data, function (index, val) {
var optionTag = $('<option></option>');
$(optionTag).val(val.Value).text(val.Text);
$('#ddModel').append(optionTag);
});
var a = '';
}
(4) The rendered html gets sent to the client
(5) Your ajax request gets triggered
(6) On success, a gets set to the empty string.
As you had mentioned in the comments of your question, the solution to this problem is to include a in the Json object returned by your action method, and access it using data.a in your script. The return line would look like
return Json(new {
model = vehModel,
a = Price
});
Keep in mind that if you do this, you'll have to access model data in your ajax success function with data.model.Field. Also, you shouldn't need to specify the JsonRequestBehavior.AllowGet option, since your method only responds to posts and your ajax request is a post.