Post JSON to Asp.net through AngularJS - c#

I currently am working on a website just for fun using AngularJS and ASP.net, this post is a more generalized question because I'm not wondering exactly how to do this, I'm more or less wondering what the best practices are. Currently I have a method in Angular like this
$scope.submit = function () {
console.log(JSON.stringify($scope.form));
$http.post("/post/new", "'" + JSON.stringify($scope.form) + "'").
success(function (data, status, headers, config) {
console.log("Success")
$location.path("/news");
}).error(function (data, status, headers, config) {
console.log("Error");
});
};
And then my corresponding Asp.net code:
[HttpPost][Route("New")]
public IHttpActionResult New([FromBody] string input)
{
JObject json = JObject.Parse(input);
Post p = new Post { Title = (string)json["title"], content = (string)json["content"] };
db.Posts.Add(p);
db.SaveChanges();
return Ok();
}
However I don't believe this is best practice, because first I'm sending everything in as a string and parsing it, but also because if my Title or Content items have an ' character then the program errors out. I'm wondering what is the best way to do this. I believe another way to do it is to pass in my model as parameters to my method, but I'm wondering if there are also other ways to do this besides that as well. Like I said, this isn't an extremely specific question, I just want to know best practices. (A little bit of code to back up your response would be much appreciated)
Thanks!

You should allow JSON.Net to do the deserialization for you in the pipleline rather than in your method. In addition, just post the object itself rather than building out a json string
$scope.submit = function () {
$http.post("/post/new", $scope.form).
success(function (data, status, headers, config) {
console.log("Success")
$location.path("/news");
}).error(function (data, status, headers, config) {
console.log("Error");
});
};
[HttpPost][Route("New")]
public IHttpActionResult New([FromBody] Post input)
{
db.Posts.Add(input);
db.SaveChanges();
return Ok();
}

Related

AngularJS Save File From ASP.NET MVC Controller

I am returning a file from an ASP.NET MVC controller and I want to download it as an attachment using AngularJS.
MVC Controller:
return File(renderedBytes, mimeType);
AngularJS:
function generatePDF(reportRequest) {
var reportController = "Report";
var controllerUrl = ngAppSettings.homeBaseUri + reportController + "/GeneratePDF";
var deferred = $q.defer();
$http({
method: "POST",
url: controllerUrl,
data: reportRequest
}).success(function (data, status, headers, cfg) {
//window.open(controllerUrl, "_self", "");
deferred.resolve(data);
}).error(function (err, status) {
deferred.reject(err);
});
return deferred.promise;
};
I've tried various ways as suggested on the similar questions about this but I'm not getting it.
I've tried this too.
My breakpoints hit without any problems inside the GeneratePDF controller but nothing happens after that. How would I go about this?
EDIT:
I also tried angular file saver but I'm getting an error that the format should be in BLOB. If I can only convert the response to a blob then I think this might be it.
TIA
If your C# Controller endpoint returns a FileContentResult (which it appears that it does), then you shouldn't need to worry about promises. You can simply do the following...
function generatePDF(reportRequest) {
var reportController = "Report";
var controllerUrl = ngAppSettings.homeBaseUri + reportController + "/GeneratePDF";
window.open(controllerUrl, "_blank");
};
I am doing this in one of my apps and it is working as expected. Is there a particular reason you were using the $q service to return a promise?

No action was found that matches the request URI

I have attempted to modify one of my api controller to allow for the creation of multiple reservations by allowing one of the parameters to be passed in as a pipe delimited string. The method and class can be seen here:
public class ReservationsController : ApiController
{
public HttpResponseMessage PostReservation(string eRaiderUserName, string SpaceNumbers)
{
char[] delimiter = { '|' };
string[] spaces = SpaceNumbers.Split(delimiter);
bool saved = true;
foreach(string space in spaces)
{
var reservation = new Reservation { eRaiderUserName=eRaiderUserName, SpaceNumber=Convert.ToInt32(space) };
if (true)
{
reservation.Game = db.Games.FirstOrDefault(g => g.ID == AppSettings.CurrentGameID);
db.Reservations.Add(reservation);
db.SaveChanges();
//HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, reservation);
//response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = reservation.ID }));
//return response;
}
else
{
saved = false;
//return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
}
db.SaveChanges();
if (saved)
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created);
response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = 1 }));
return response;
} else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
}
}
I have a form that posts what I think should be the right information, but I keep getting this error:
{"$id":"1","Message":"No HTTP resource was found that matches the request URI 'http://localhost:58463/api/Reservations'.","MessageDetail":"No action was found on the controller 'Reservations' that matches the request."}
The (modified) save method in the api is still definitely a work in progress. But what is keeping this from finding the web api controller? Here is the firebug output:
As pointed out, the problem is that a POST action can only transfer the data posted in the body to a single object (for technical reasons).
That means that you can get data from the route data, from the querystring, and from the body, with the following limitations:
data from querystring or route data must be single values (i.e. they cannnot be classes), in any number
you can have only one parameter of the action with data coming from the request body, but this can be a complex class
you can make any combination of this, i.e. a single or complex param coming from the body, and any number of single parameters coming from the route data or the querystring.
So, the most generic way to solve your problem (i.e. that can be easyly applied to other classes where you need to pass complex data, even more complex than this case) is this:
First, make a class which has properties for all the needed data,in your case:
public class ReservationData
{
public string eRaiderUserName { get; set; }
public string SpaceNumbers { get; set; }
}
Second, use this class as the type of the received parameter in your action:
public HttpResponseMessage PostReservation(ReservationData reservationData)
With this code the formatter can map all the data in the request body to a single parameter in the action. You can use JSON or formdata formats, like the generated by jQuery.
NOTE: the property names must case-sensitively match the name of the posted parameters.
This is because you send x-www-form-urlencoded data to controller, to handle this data you must use [FromBody] before parameter like
public HttpResponseMessage Post([FromBody] string name) { ... }
but this approach has a lot of limitation:
1) There can be only one parameter marked [FromBody] attribute (it can be complex type)
2) The data must be encoded as =value not as key=value .
You can read it here description and how make it work here example .
If it possible i recommend you to send Json data to controller, without this limitation.
Web API has limited support to map POST form variables to simple parameters of a Web API method. Web API does not deal with multiple posted content values, you can only post a single content value to a Web API Action method.
public HttpResponseMessage PostReservation(string eRaiderUserName, string SpaceNumbers)
{ //...}
and you are trying to call using jQuery:
$.ajax({ url: 'api/reservations', type: 'POST', data: { ... }, dataType: 'json', success: function (data) {alert(data);} });
Unfortunately, Web API can’t handle this request and you’ll get error. But if you pass parameters using query string, It’ll work:
$.ajax({ url: 'api/reservations?eRaiderUserName=2012&SpaceNumbers=test', type: 'POST', dataType: 'json', success: function (data) { alert(data); } });
But it’s not good solution and not applicable for complex objects. So here are the different ways to do it.
Using Model Binding (Preferred)
Using Custom Parameter Binding
FormDataCollection
Query String

AJAX error in ASP.NET c#

I am very new to Ajax and ASP.NET MVC. I have a function, that returns back to AJAX and I need to handle the error situation. When everything works fine, then the code is okay. My question is how to handle the error part. Here is what I have:
To return success I have:
var data = new { success = false };
return Json(data, JsonRequestBehavior.AllowGet);
And I need to know what to return when there is an exception or error??
This is my query:
function DoMailPDF() {
$("#submitMail").attr("disabled", true);
var personid = $("#personid").val();
var unitid = $("#unitid").val();
var url = "#(Url.Action("SendEmail", "Report"))";
$.ajax({
url: url,
data: { person: personid , unit:unitid},
success: function () {
// $('input[name=MailSent]').attr('checked', true);
$("#submitMail").removeAttr("disabled");
alert("Email sent!");
},
error: function () {
alert("Email not sent!");
}
});
}
It never comes to the error function. How do I make it go to the error? Any tips and suggestions are most welcome.
You can access your json response object by writing:
$.ajax({
url: url,
data: { person: personid , unit:unitid},
dataType: 'json',
success: function (response) {
if (response.success == false) {
// Error handling
} else {
// Success handling
}
},
error: function () {
alert("Email not sent!");
}
});
As Nick Bork already explained in a comment, the error/success status of a response is determined by the Http status code that is sent down in the header. You can still go the suggested way and inspect the response object and the success property but it is clearly not the proper way when you already have a more powerful and long proven mechanism (the HTTP protocol itself).
.NET will use HTTP 200 (OK) when everything goes according to the code but you can change this behaviour in the Controller by accessing the Reponse object like this, for example:
Response.StatusCode = 500; // or any of the other HTTP "failure" status codes
Any status code in the 4xx or 5xx category will trigger the error() handler specified in the $.ajax(...) call. From there you can of course also inspect the proper status code, the response details and every properties of the XHR object to provide a more meaningful user experience.
HTTP status codes are pretty much set in stone and are not likely to change, that's why they are in my opinion definitely preferrable to a custom made solution...
PS: For a list of HTTP status codes, wikipedia is your friend.

Calling a web service from Javascript (passing parameters and returning dataset)

I have created a web service in C# and now need to call it from a mobile app. I'm trying to create a Windows 7 mobile app, but using HTML5 and Javascript not the native code. The web service takes 2 parameters, Email and Password, and returns a Dataset. I don't really have any javascript experience (or web services experience for that matter, trying to learn with this project), and when trying to research how to call a web service using javascript I just found too much information and didn't know where to begin because so many other technologies were also mentioned.
So I decided to try things out and this is what I came up with so far:
<script type="text/javascript">
document.addEventListener("deviceready", onDeviceReady, false);
// once the device ready event fires, you can safely do your thing! -jm
function onDeviceReady() {
}
function LoginButton_onclick() {
UpdateChildrenApp.PhoneWebServices.GetMyChildren(document.getElementById('EmailBox').value,document.getElementById('PasswordBox').value, OnComplete, OnError)
}
function OnComplete(result) {
for (var i = 0; i < result.tables[0].rows.length; i++)
document.getElementById('Test').innerHTML += ''+(result.tables[0].rows[i].col_name);
}
function OnError(result) {
document.getElementById('Test').innerHTML ='Error :'+result.get_message();
}
</script>
This code does nothing when I press the submit button. Could someone please point out what the problems are and how I can fix them or suggest what I should research to address the problems and put me on the right track? Any help is greatly appreciated.
First, your webservices should return a JSON object if you want to use it in javascript.
You can of course return any XML/string, but using JSON will be A LOT easy to use the data in javascript.
Then, I would advise you to use jquery to call the webservice, as jquery will do a lot of work for you.
Read this article, it should help you set different components correctly:
I would use jQuery to do this kind of thing.
The ajax functionality its provides is really easy to use.
I would use the Revealing Module Pattern (RMP) and 2 javascript files. If you're unfamiliar with the RMP, there is a great post covering it here:
http://weblogs.asp.net/dwahlin/archive/2011/08/02/techniques-strategies-and-patterns-for-structuring-javascript-code-revealing-module-pattern.aspx
I find that if I dont employ some kind of structure to my js code using the RMP, I just end up with a mess of functions in one file.
Id have Startup.js and Dataservice.js and they would look something like this:
Startup.js
var Startup = function () {
var isValid,
dataObject = {},
populateDataObject = function () {
dataObject.dealer = $("[id$='_txtUser']").val();
dataObject.password = $("[id$='_txtPassword']").val();
},
init = function () {
var dealerId = 0;
$("[id$='_SubmitButton']").bind('click', function (evt) {
evt.preventDefault();
populateDataObject();
if (isValid) {
Dataservice.processLoginRequest(dataObject, processLoginRequestResult);
}
});
};
return {
init: init,
processLoginRequestResult: processLoginRequestResult
};
} ();
Dataservice.js (assumes old school .asmx, change as needed)
var Dataservice = function () {
$.ajaxSetup({
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json"
});
var serviceBase = '../services/LoginService.asmx/',
processScreenRequest = function (valObject, callback) {
$.ajax({
url: serviceBase + "ProcessLoginRequest",
data: JSON.stringify(valObject),
success: function (json) {
callback(json);
}
});
};
return {
processScreenRequest: processScreenRequest
};
} ();
and then I would include refereces to these 2 js files as well as jquery in my html page.
I hope this helps.
I've used Dojo for this once, its pretty simple you can make xhrget or xhrpost requests. It has a function called load that is the callback where you can modify the contents of the HTML components in the page.
Use these links : http://dojotoolkit.org/reference-guide/1.7/dojo/xhrGet.html

Making an Ajax request to a page method in ASP.NET MVC 2

I'm trying to call a page method belonging to a MVC Controller from another site, by means of:
$.ajax({
type: "GET",
url: "http://localhost:54953/Home/ola",
data: "",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data) {
console.log(data.Name);
}
});
the method code is as follows, really simple, just to test:
public ActionResult ola()
{
return Json(new ActionInfo()
{
Name = "ola"
},JsonRequestBehavior.AllowGet);
}
I've seen this aproach being suggested here, and I actually like it a lot, should it work...
When I run this, firebug gets a 200 OK, but the data received is null.
I've tried a lot of different approaches, like having the data in text (wish grants me "(an empty string)" instead of just "null") or returning string in the server method...
Can you tell me what am I doing wrong?
Thank you in advance,
João
Have you tried returning your JSON like so...
public ActionResult ola()
{
return Json(new { Name = "ola" }, JsonRequestBehavior.AllowGet);
}
Controller:
public ActionResult Ola()
{
// No need to use a custom ActionInfo type here, an anonymous type
// will be just fine:
return Json(new { Name = "ola" }, JsonRequestBehavior.AllowGet);
}
View:
$(function {
$.getJSON('/home/ola', function(json) {
alert(json.Name);
});
});
You could try returning JsonResult from the controller action method. Method signature would then be public JsonResult ola(). Hope it helps.
Thanks for all the feedback. I found out that everything I was doing was right and wrong at the same time.
the requests were all functional, but the request was being made to a different domain, wich is automatically blocked by the browsers (except IE). It's a question of security.
But since the request was meant to work on a mobile device, when i tested it there, it worked perfectly.
Once again, thanks to everyone who answered, i'll adopt some of the ideas shown here :)
if you are making an ajax call cross domain. Have you tried setting your data type to
dataType: jsonp
jquery ajax cross domain

Categories

Resources