In my web Api project I am using parameterized methods and not calling by method name. I am using $resource in my angular code and this call works perfect.
For example this gets me a list of contacts:
public class LeadsController : ApiController
{
public IEnumerable<Contact> Get()
{
var contacts = new ContactRepository();
return contacts.BuildContacts();
}
}
The only problem I have is the casing so then I use newtonsoft and have to change the return type to string for it to work
public class LeadsController : ApiController
{
public string Get()
{
var contacts = new ContactRepository();
var settings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };
return JsonConvert.SerializeObject(contacts, Formatting.Indented, settings);
}
}
Now the issue I have is the angular is expecting an array but it is returning an object (string) so I am having errors. Here is my angular
return $resource('http://localhost:33651/api/Leads/', {
get: { method: 'GET', isArray: false },
query: {
method: 'GET',
isArray: true
}
});
Is there a way on my web api method I can return IEnumerable and have the Json formatted in camel case correctly? What is the best way I should handle my situation?
Thanks for the help
Web API already uses Newtonsoft serializer, so you need only to configure it. Add these lines to WebApiConfig.Register method:
var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
And return IEnumerable<Contact> instead of the string, please take a look at this sample project https://github.com/maxbrodin/camel-case-serialization-webapi
Edited
Related
I am trying to pass an integer and string parameters from an AngularJS client to an ASP.NET Web API server, without using a POCO class to wrap the parameters in. I've tried the following:
The parameters I want to pass are "id", which is an integer, and "name", a string.
My AngularJS service looks like this:
function myResource($resource, myServerUrl) {
return {
testFunction: $resource(myServerUrl + "/api/testing/:id/:name/MethodB", null,
{
'get': { method: 'GET' }
})
};
}
The code in the AngularJS controller is the following:
var vm = this;
vm.testFunction = function (Id, Name) {
myResource.testFunction.get({ id: Id, name: Name },
function(response) {
// Do something
},
// Handles errors
function(error) {
// Process error
});
}
And finally, the Web API controller:
[RoutePrefix("api/testing")]
public class MyController : ApiController
{
// This is NOT the method I am using for hit example.
// It's a different one with a similar signature
// so I am showing it here just in case it has
// impact on what I am trying to do.
[Authorize]
[Route("{name}/{id:int}/MethodA")]
public IHttpActionResult GetData(string name, int id)
{
// Do something
}
// This is the method I am using for this example
[Authorize]
[Route("{id:int}/{name}/MethodB")]
public IHttpActionResult MyTestMethod(int id, string name)
{
// Do something
}
}
When I try to run the above code, I get the following error:
{"message":"The requested resource does not support http method 'GET'."}
If I change the code to use POST instead of GET, i.e.:
testFunction: $resource(myServerUrl + "/api/testing/:id/:name/MethodB", null,
{
'get': { method: 'POST' }
})
and
// This is the method I am using for this example
[Authorize]
[HttpPost]
[Route("{id}/{name}/MethodB")]
public IHttpActionResult MyTestMethod(int id, string name)
{
// Do something
}
I get this:
{"message":"The requested resource does not support http method 'POST'."}
And if I modify my AngularJS service to not use colon in front of the parameters, i.e. this:
testFunction: $resource(myServerUrl + "/api/testing/id/name/MethodB", null,
{
'get': { method: 'POST' }
})
I get this error instead:
{"message":"The request is invalid.","messageDetail":"The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Web.Http.IHttpActionResult MyTestMethod(Int32, System.String)' in 'MyController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter."}
What is the problem here? How can I pass an integer and a string from AngularJS to a Web API controller, without using a POCO class? I am aware I can wrap both parameters in a value object and pass it that way to the Web API, but that's unnecessary complexity for me at this point. There should be a simple way to do this.
I've done this with two or three integer parameters without a problem, but for some reason an integer and a string is not working. Any advice on this would be appreciated. It's one of those things that should be simple to do, but apparently it's not.
Ok here's an example where I passed an object from controller to service, and the service uses $resource
var navApp = angular.module('navApp', [
'ngResource',
'ui.bootstrap',
'ngAnimate'
]);
navApp.controller('menuController', [
'$scope',
'navSectionList',
'navGetCategories',
function ($scope, navSectionList, navGetCategories) {
$scope.navSectionList = navSectionList.query();
$scope.getSectionID = function (event) {
$scope.navGetCategories = navGetCategories
.getResource([event])
.query();
};
}
]);
navApp.factory('navSectionList', [
'$resource',
function ($resource) {
return $resource('/api/navigation/section/list', {}, {
query: { method: 'GET', params: {}, isArray: true }
});
}
]);
navApp.factory('navGetCategories', [
'$resource',
function ($resource) {
var service = {
getResource: function (sectionID) {
return $resource('/api/navigation/category/' + sectionID, {}, {
query: { method: 'GET', params: {}, isArray: true }
});
}
};
return service;
}
]);
getSectionID kept passing undefined to navGetCategories.getResource() until I put event into a box [event].
I still don't really know why it wouldn't work without the square brackets, maybe someone else can explain why.
well, I do it this way
Server
[HttpGet]
[Route("Api/Account/GetPasswordReset")]
public dynamic GetPasswordReset(string UserName, string OldPassword, string NewPassword)
{}
Client
$http({
method: "GET",
url: CTHelper.ApiUrl() + '/Api/Account/GetPasswordReset?UserName=' + CTHelper.UserName()
+ '&OldPassword=' + $scope.CurrentPassword + '&NewPassword=' + $scope.NewPassword,
}).then(function mySuccess(response) {
}, function myError(response) {
});
In MVC, you can do something like this:
public ActionResult Index()
{
return Json(new List<DateTime> { DateTime.Parse("19/02/2017") },
JsonRequestBehavior.AllowGet);
}
And the returned value is ["\/Date(1487458800000)\/"], which is a Javascript Date object.
However, using WebAPI like this:
public IEnumerable<DateTime> Get()
{
return new List<DateTime> { DateTime.Parse("19/02/2017") };
}
The returned value is <dateTime>2017-02-19T00:00:00</dateTime>
Is there any way that I can serialize a DateTime as a Javascript Date object using WebApi?
You can use that format with JavaScript though:
var myDate = new Date("2017-02-19T00:00:00");
If you change your Accept header on your request to application/json you get:
["2017-06-09T08:14:13.7729697-03:00"]
Try with a tool like Postman.
In angular, you can do something like:
var config = { headers: {
'Accept': 'application/json',
}
};
$http.get("/api/values", config);
I am creating a pdf using pdfsharp. I need to pass the chart legend data(name,color) to the pdfsharp controller. I am using a angular $http post, a ajax post would be fine as well. the error I am getting is
Request URL:http://localhost:46691/api/exportChartPdf/[object%20Object],[object%20Object],[object%20Object],[object%20Object],[object%20Object],[object%20Object],[object%20Object],[object%20Object],[object%20Object],[object%20Object],[object%20Object],[object%20Object],[object%20Object],[object%20Object],[object%20Object],[object%20Object]
do i need to some how pass it as a string? if so how would I parse it in the api controller back to the way I need it?
the objects i am trying to pass back
0: Object
color: "rgb(67,134,215)"
name: "Fleming Place - Miscellaneous Spec Builders"
__proto__: Object
1: Object
2: Object
3: Object
4: Object
javascript
var legendModel = $scope.seriesData.map(function (a) {
return {
color: a.color,
name: a.name
};
});
$http.post('/api/exportChartPdf/' + legendModel);
api controller
[HttpPost]
public PDF Post() // allow nullable parameter
{
try
{
You should be posting the object on the form body, not on the querystring. In addition, your Web API controller should receive a strongly typed object that mirrors the data that you're passing.
public class Data
{
public string Color { get; set; }
public string Name { get; set; }
}
[HttpPost]
public PDF Post([FromBody]List<Data> data)
{
...
}
And then simply post the object.
var legendModel = $scope.seriesData.map(function (a) {
return {
color: a.color,
name: a.name
};
});
$http.post('/api/exportChartPdf/', legendModel);
Looks like your controller action is missing parameter on it,
[HttpPost]
public PDF Post(SomeClass legendModel) // allow nullable parameter
{
try
{
SomeClass would contain color & name properties.
Then you should correct your $http.post call, pass 2nd param as data in JSON format.
$http.post('/api/exportChartPdf', { legendModel: legendModel);
I am trying to get metadata back from my "contact" object to breeze so I can map the metadata to a "contactdto" object. On the server I have a Web API function called GetContactsMetadata
[HttpGet]
public IQueryable<Contact> GetContactsMetadata()
{
return _contextProvider.Context.Contacts.Take(1);
}
I'm sure I'll remove the IQueryable and/or list once I get this example running. on the client I have the following
//GetContactsMetadata
var myJsonResultsAdapter = new breeze.JsonResultsAdapter({
name: "GetContactsMetadata",
extractResults: function (json) {
return json.results;
},
visitNode: function (node, parseContext, nodeContext) {
var entityType = normalizeTypeName(node.$type);
var propertyName = nodeContext.propertyName;
var ignore = propertyName && propertyName.substr(0, 1) === "$";
return {
entityType: entityType,
nodeId: node.$id,
nodeRefId: node.$ref,
ignore: ignore
};
}
});
var dataService = new breeze.DataService({
serviceName: 'api/contacts',
jsonResultsAdapter: myJsonResultsAdapter
});
var manager = new breeze.EntityManager({ dataService: dataService });
It keeps erroring in chrome with: "normalizeTypeName is not defined". Am I calling the JsonResultsAdapter correctly?
I should have been clearer in the example.
The normalizeTypeName method is a method you as the dev would write that would take some property on the node and return a Breeze EntityType or a Breeze EntityType name. If you actually know the type name and are only using this adapter for a single type of query you can do something as simple as this:.
visitNode: function (node, parseContext, nodeContext) {
return {
entityType: "Contact" // or "ContactDTO" depending on what you are calling the type on the client.
};
}
I want to call a web service method in javascript. (asp.net 3.5)
I have traced the result with firebug .
here is the result:
{"d":"[{\"TI\":\"www\"},{\"TI\":\"www1\"}]"}
I think the correct result should like this
{"d":[{\"TI\":\"www\"},{\"TI\":\"www1\"}]}
what is the quotation before and after the Bracket ?
// edited :
in webserivce:
public class Test
{
public Test(string t){T1 = t;}
public string T1 { set; get; }
}
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true, XmlSerializeString = false)]
public string Load(string e)
{
List<Test> post = new List<Test> { new Test("www"), new Test("www1") };
return JsonConvert.SerializeObject(post);
}
and in js file :
var store = new Ext.data.JsonStore({
proxy: new Ext.data.HttpProxy({
url: '/core/webservice/service.asmx/Load',
method: 'GET',
headers: { 'Content-type': 'application/json' }
}),
root: 'd',
id: 'Id',
fields: ['TI']
});
store.load({ params: { e: ''} });
return;
thank you .
mir
You shouldn't need to serialize manually in the web service; consider using something like this instead:
public List<Test> Load(string e)
{
List<Test> post = new List<Test> { new Test("www"), new Test("www1") };
return post;
}
Since you're using string as your return object, it will convert it as that for you when serializing it (once again).
The quotation indicates that this is a string, so :
var b = {"d":"[{\"TI\":\"www\"},{\"TI\":\"www1\"}]"};
b["d"] will return a string instead of array of objects.
You can either go around this with the following in javascript:
var c = eval(b["d"]);
which will turn the string into an array of objects.
Or the better way, post the code that is returning this and we can try to figure out why it is returned as a string.