Can´t consume Json from MVC and Web API controller - json

I'm trying to consume json data from a web API in .NET. I tried by two ways, with web API and returning Json with a MVC controller but I can't consume from any of both. I only can consume it from a view inside my project, but when I try to consume with a html page outside my project it throws an error.
It is hosted in azure. Here is the code of the Action.
public ActionResult PreguntasById(int id)
{
var emp = db.pregunta_area.Where(i => i.fk_pregunta == id).Select(e => new
{
id = e.fk_pregunta,
pregunta = e.Preguntas.pregunta,
area = e.fk_area
}
).ToList();
return Json(emp, JsonRequestBehavior.AllowGet );
}
And my AJAX petition.
function siguientePregunta()
{
$("#pregunta").remove();
$.ajax({
type: "GET",
dataType: 'json',
url: 'http://carrierintegrator.azurewebsites.net/Preguntas/PreguntasById/'+contador,
async: true,
success: function (response) {
$("#pregunta-content").append("<h6 id='pregunta'>"+response[0].pregunta+"</h6>");
console.log(response);
},
error: function (obj, error, objError) {
alert("Error interno: " + objError);
console.log(id_pas);
}
});
contador++;
}
Also I tried to quit the dataType but it's useless. I don't know what it's going wrong.
I'm doign the same in the Web API Controller but i'm having the same error.

Related

ASP MVC Areas and JSON POST

I have a project with areas and would like to post a view model as JSON to a controller method.
This is what I have, with performance being generated in the default area and passed to the view in area SeatSelection:
$("#addToCartButton").click(function () {
var json = #Html.Raw(Json.Encode(performance));
$.ajax({
url: 'https://#(Request.Url.Host)/SeatSelection/Home/AddToCart',
type: 'POST',
dataType: 'json',
data: json,
contentType: 'application/json; charset=utf-8',
success: function (data) {
alert(data);
}
});
});
And the action method for testing:
[System.Web.Http.Route("SeatSelection_AddToCart")]
[System.Web.Http.HttpPost]
public JsonResult AddToCart(PerformanceViewModel performance)
{
return Json(performance.Name);
}
I created the following route:
context.MapRoute(
"SeatSelection_AddToCart",
"SeatSelection/Home/AddToCart",
new { action = "AddToCart", controller = "Home", id = UrlParameter.Optional },
namespaces: new string[] { "myProject.Areas.SeatSelection.Controllers" }
);
But all I get is a internal server error 500. I also tried to use [FromBody] and setting a breakpoint to the method, but it is not invoked. I can't figure out what's wrong or missing, please help.
UPDATE
This is the json / performance:
PerformanceID=00000000-0000-0000-0000-000000000000&Name=Performance+15&StartDate=%2FDate(1360364400000)%2F&EndDate=%2FDate(1500328800000)%2F&LatestDateBookable=%2FDate(1450911600000)%2F&Organizer=Organizer+15&Location=Location+15&Availability=75&IsFull=false&IsBookable=true&HasPrice=true&BookableSeats=11&BookedSeats=94&Description=Description+of+Performance+15&Price=443
I found an error: "invalid json primitive: performanceid"
First of all, I would recommend you to use #Url.Action helper method instead of generating url like this: https://#(Request.Url.Host)/SeatSelection/Home/AddToCart.
Secondly, always validate params which comes from the browser. return Json(performance.Name) looks suspicious. What is performance will be null? This might be a problem of your internal server error 500.
If this is not a problem then try to send string instead of JSON to the server and validate and parse JSON on the server side.
You can use Url.Action method like this. I suppose SeatSelection is an area in your project.
$.ajax({
url: '#Url.Action("AddToCart", "Home", new { Area = "SeatSelection"})',

Watson SpeechToText Java and javascript model differences

I'm working on integrating the watson-speech.js javascript library with a Spring-based server using the Watson Java SDK. I'm trying to send the output from a WatsonSpeech.SpeechToText.recognizeMicrophone call to the server with no luck. The Speech java classes appear to have the appropriate #SerializedName annotations that match the json being sent from the client, but I'm getting UnrecognizedPropertyException errors from Jackson.
Unrecognized field "keywords_result" (class com.ibm.watson.developer_cloud.speech_to_text.v1.model.SpeechResults), not marked as ignorable (2 known properties: "resultIndex", "results"])
Here's the controller method:
#RequestMapping(value = "/postWatsonRequest", method = RequestMethod.POST)
#ResponseBody
#ResponseStatus(value=HttpStatus.OK)
public ResponseObject postWatsonRequest(#RequestBody SpeechResults speechResults) {
...
}
I'm clearly missing something. Do I need to unpack the json manually on the server side (custom deserializer?) or format it into an acceptable json string on the client side?
It turned out to be a couple of mistakes on my part and although I'm not sure this is the best solution it does work. Here's the full code for anyone that's interested. Key things that made it work:
You must use the receive-jason event to capture the full json result. The data event appears to only return the final text
The result data had to be wrapped in a valid json wrapper - data:{message:data} (this was my big mistake)
Do not include contentType: 'application/json; charset=utf-8', in the ajax call or the controller will not recognize the json data
The Watson Java SDK WebSocketManager receives an okhttp3.ResponseBody from Watson from which it extracts a string. I presume this is similar to what the javascript SDK receives so I used the same code from the WebSocketManager to convert the JSON.stringify string to a SpeechResults object in the controller.
From the okhttp3.ResponseBody javadoc:
A one-shot stream from the origin server to the client application with the raw bytes of the response body
Watson javascript
function listen(token) {
stream = WatsonSpeech.SpeechToText.recognizeMicrophone({
token: token,
readableObjectMode: true,
objectMode: true,
word_confidence: true,
format: false,
keywords: keywordsArray,
keywords_threshold : 0.5,
continuous : false
//interim_results : false
//keepMicrophone: navigator.userAgent.indexOf('Firefox') > 0
});
stream.setEncoding('utf8');
stream.on('error', function(err) {
console.log(err);
stream.stop();
});
stream.on('receive-json', function(msg) {
console.log(msg);
if (msg.state != 'listening') {
if (msg.results[0].final) {
console.log('receive-json: ' + msg);
postResults(msg);
stream.stop();
}
}
});
}
Ajax post
function postResults(results) {
var data = JSON.stringify(results);
console.log('stringify: ' + data);
$.ajax({
type: 'POST',
url: appContextPath + '/postWatsonResult',
dataType: 'json',
data: {message:data}
})
.done(function(data) {
console.log('done data: '+ data);
})
.fail(function(jqXHR, status, error) {
var data = jqXHR.responseJSON;
console.log('fail data: '+ data);
});
}
Spring controller
#RequestMapping(value = "/postWatsonResult", method = RequestMethod.POST)
#ResponseBody
#ResponseStatus(value=HttpStatus.OK)
public ResponseObject postWatsonResult(#RequestParam("message") String message, Locale locale) {
logger.info("postWatsonRequest");
JsonObject json = new JsonParser().parse(message).getAsJsonObject();
SpeechResults results = null;
if (json.has("results")) {
results = GSON.fromJson(message, SpeechResults.class);
}
if (results != null) {
logger.debug("results: " + results.getResults().get(0).getAlternatives().get(0).getTranscript());
}
return new ResponseObject();
}
I still think it should be possible somehow to use #RequestBody SpeechResults speechResults so I'll continue to play around with this, but at least I have a working solution.

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 :)

How to send multiple parameters from kendo data source read operation to WebApi controller

I have the following scenario: I have a kendo.dataSource which is populated via read request to a WebApi Controller. In addition to the read, I am sending a couple of parameters, which then I use in my controller to do some server logic. I was able to send as many simple parameters as I want via the parameterMap property of the transport function. Till now it was a simple get request. However now I need to send additional json object to the controller as a parameter. I read that I have to transform the Get request to Post and put the Json onto the body of the request but I don't know how to do it.
The code that I have so far:
var gridDataSource = new kendo.data.DataSource({
type: 'odata-v4',
transport: {
read: {
url: wave.alarmsAndEvents.api('api/alarmsAndEventsSearch/post'),
type: "POST",
data: {
SearchModel: JSON.stringify(vm.searchModel)
},
contentType: 'application/json; charset=utf-8',
},
parameterMap: function (data, operation) {
if (operation === "read") {
data.startDate = kendo.toString(vm.selectedTimeInterval.start, "G");
data.endDate = kendo.toString(vm.selectedTimeInterval.end, "G");
data.alarmsToDisplay = vm.maxRecords;
}
return kendo.stringify(data);
}
},
pageSize: vm.maxRecords,
error: function (e) {
alert(e.xhr.responseText);
}
});
The SearchModel is the thing that I want to send as JSon. The rest are simple DateTime and int parameters.
My controller:
[HttpPost]
public IQueryable<AlarmsSearchViewModel> Post(DateTime startDate, DateTime endDate, int alarmsToDisplay, [FromBody]JToken jsonbody)
{
....
return something;
}
I end up with Not Found 404, but I am pretty sure that I have messed up the parameters. And from the Network window I can see that the json object is not sent at all. Any help will be much appreciated!

Send generic JSON data to MVC2 Controller

I have a javascript client that is going to send json-formatted data to a set of MVC2 controllers. The client will format the json, and the controller will have no prior knowledge of how to interpret the json into any model. So, I can't cast the Controller method parameter into a known model type, I just want to grab the generic json and pass it to a factory of some sort.
My ajax call:
function SendObjectAsJSONToServer(object,url,idForResponseHTML) {
// Make a call to the server to process the object
var jsonifiedObject = JSON.stringify(object);
$.ajax({
url: url // set by caller
, dataType: 'json'
, data: jsonifiedObject
, type: 'GET'
, error: function(data) { alert('error in sendObjectAsJSONToServer:' + data); }
, success: function(data) {
alert(data.message); // Note that data is already parsed into an object
}
});
}
My MVC Controller:
public ActionResult SaveForm(string obj)
{
// Ok, try saving the object
string rc = PassJSONToSomething(obj.ToString());
string message = "{\"message\":\""+rc+"\",\"foo\":\"bar\"}";
return new ContentResult { Content = message, ContentType = "application/json" };
}
The problem is that obj is always null. Can anyone tell me how I should structure the ajax call and the controller parameter so that I get my json to the server? I'm using MVC2. This may appear to be a duplicate of some SO questions, but in my case I do not know the Model that the json maps to, so I can't use a specific model type in the controller parameter type.
Thanks very much.
Have you tried something like that?
$.ajax({
url: url // set by caller
, dataType: 'json'
, data: {obj :jsonifiedObject}
, contentType: 'application/json; charset=utf-8'
, type: 'GET'
, error: function(data) { alert('error in sendObjectAsJSONToServer:' + data); }
, success: function(data) {
alert(data.message); // Note that data is already parsed into an object
}
});