I have a class in TypeScript that has attributes written in camelCase.
The instance of that class needs to be used in an http request body that deals with a webservice.
The issues is, the WebService's Backend is written in C#, and it's trying to access the attributes using UpperCamelCase notation.
How can I convert the attributes of a class from camelCase to UpperCamelCase when sending it in an http request ?
Example:
class Test1:
httpClient: CustomHttpClient;
public attributeOne
public attributeTwo
constructor(att1,att2):{
this.attributeOne = att1;
this.attributeTwo = att2;
this.httpClient = new CustomHttpClient();
}
sendRequest(){
const test = new Test1();
this.httpClient.post(url, test , null);
}
The WebService will try to access the body likeWise:
test.AttributeOne
test.AttributeTwo;
Therefore causing an error since no such attributes exist.
I don't want to change my attributes in TS to UpperCamelCase for linting reasons, etc..
How do I achieve this?
Try using HttpParams to set the request body attribute names to whatever you want. Example:
const params = new HttpParams()
.set('para1', "value1")
.set('para2',"value2");
const body=JSON.stringify(person);
return this.http.post<Person>(this.baseURL + 'people', body,{'headers':headers, 'params': params})
Taken from this https://www.tektutorialshub.com/angular/angular-http-post-example/
I managed to do it like wise:
I installed an npm package called 'camelcase-keys' ( npm install camelcase-keys)
I pass my object as a parameter like this:
const body = camelcaseKeys(JSON.parse(JSON.stringify(companyDetails)), { deep: true, pascalCase: true });
Related
Trying to get a basic model of my functions working.
Frontend (Angular): the body data will be JSON of this class:
class BackendParams {
listValues: any;
constructor( netList: any ) {
this.listValues = netList;
}
}
Then a function creates the class object:
const params = new BackendParams(list);
then calls a (still in the front-end) Angular function to send it to the backend:
onClickTest(params: any) {
const A = 1;
const B = 2;
const NameString = 'test';
const formData = new FormData();
formData.append('NetworkList', JSON.stringify(params));
let url = `${this.url}/CalibrationModel/1/2/SampleTest/TestModel`;
this.http.post(url, formData).subscribe(
(data) => {
console.log(data);
});
}
BACKEND:
class BackendParams
{
List<Constituent> listNetworkConstituents;
}
The following is image of the source code so you can see the syntax red underlines
I don't think the two are related (or are they?) but referencing the body parameters is of course essential.
And, of course, let me know anything else you see that might be a problem.
Thanks for your help. I learn a lot from you guys.
Yogi
If your method were marked as async then returning a bool would work. So public async Task<bool>..., but that isn't the case. However, as #JohnD91 said, if you're not using await in your method, it doesn't need to be async and it also doesn't need to return a Task.
The other problem is that parmsJSON is misspelled, because it's defined in the method signature as paramsJSON. You're missing the other a.
BACKGROUND
currently I am in a side project where I am building a Xamarin based mobile App for easy movie and tv show searching and navigation based on user preferences (e.g. based on movie genre etc).
To do this the mobile app acts as a client to the https://www.themoviedb.org/documentation/api online movie database's Web API service.
PROBLEM
I am looking for an easy and well supported package to wrap API Uri paths and query parameters into a web api query. I have looked a bit on RestSharp .
I like the syntax very much with the pattern based query path:
var request = new RestRequest("resource/{id}");
request.AddParameter("name", "value");
request.AddUrlSegment("id", "123");
but I am not sure about the packages future. Also if there is an alternative from MS, I would take that.
So have also looked Web-API tailored at MS alternatives but I am unsure what is recommended there. I only can find docs and examples for the server side (ASP.NET CORE MVC).
I need to be pointed to a well functioning .NET Standard 2.0 package from Microsoft or from a 3rd party to send Web API request from my Xamarin client.
Where am I
I have already written a lot of code based on pure HttPClient and AspNetcore.WebUtilituies for assembling a query string. But the gazillions of API path segments are getting out of my hand. I really need something to manage API path templates like RestSharp does
Code sample:
here I declare all of the path segments which I assemble manually ==> ugly AF
public static class WebApiPathConstants
{
public const string BASE_Address = "https://api.themoviedb.org";
public const string BASE_Path = "/3";
public const string CONFIG_Path = "/configuration";
public const string GENRE_LIST_Path = "/genre/movie/list";
...
lot of lines here
....
public const string PAGE_Key = "page";
public const string INCLUDE_Adult_Key = "include_adult";
public const string API_KEY_Key = "api_key";
public const string RECOMMENDATIONS_Path = "/recommendations";
public const string SIMILARS_Path = "/similar";
}
Here I assemble a query and kick of a task to get movie details based on the query from the server: The assembly of the Url path is my main problem. It looks too error prone.
public async Task<FetchMovieDetailsResult> FetchMovieDetails(int id, string language = null, int retryCount = 0, int delayMilliseconds = 1000)
{
string baseUrl = BASE_Address + BASE_Path + MOVIE_DETAILS_Path + "/" + id;
var query = new Dictionary<string, string>();
query.Add(API_KEY_Key, apiKeyValue);
if (!string.IsNullOrEmpty(language))
query.Add(LANGUAGE_Key, language);
string requestUri = QueryHelpers.AddQueryString(baseUrl, query);
FetchMovieDetailsResult result = await GetResponse<FetchMovieDetailsResult>(retryCount, delayMilliseconds, requestUri);
return result;
}
The result is a POCO class with the HttpStatusCode and (if successful ) a Json object. The client accesses the Json object only if the StatusCode == 2xx.
Prepared to be shot down in flames here, if this doesn't match your use-case, but it looks like the TheMovieDb site itself has a list of client libraries. It's available here: https://www.themoviedb.org/documentation/api/wrappers-libraries. They're obviously a layer higher than you're asking for here, in that they completely wrap the API, such that you need not even know what you're calling or how you're calling it, but in the interests of getting the job done, they seem like they'd do the trick.
I am trying to mock a call that returns ResourceResponse<Document>, but I am not able to instantiate that type. Is there a factory class that can instantiate it or some other way to do so?
EDIT
var response = new ResourceResponse<Document>();
The type 'Microsoft.Azure.Documents.Client.ResourceResponse' has no constructors defined
The latest stable version of Microsoft.Azure.DocumentDB (1.10.0) atm added 2 constructors for mocking purposes.
https://msdn.microsoft.com/en-us/library/azure/dn799209.aspx#Anchor_2
Edit
Using Moq you could do something like this:
Mock<IDocumentClient> documentClient = new Mock<IDocumentClient>();
documentClient
.Setup(dc => dc.ReplaceDocumentAsync(UriFactory.CreateDocumentUri("database", "collection", "id"), object, null) // last parameter are RequestOptions, these are null by default
.Returns(Task.FromResult(new ResourceResponse<Document>()));
This way I can check if the method on my documentClient is being called, if you want to influence what is returned in the document, you have to create a document, and following that a ResourceResponse of that document. Something like:
var document = new Document();
document.LoadFrom(jsonReader); // the json reader should contain the json of the document you want to return
Mock<IDocumentClient> documentClient = new Mock<IDocumentClient>();
documentClient
.Setup(dc => dc.ReplaceDocumentAsync(UriFactory.CreateDocumentUri("database", "collection", "id"), object, null) // last parameter are RequestOptions, these are null by default
.Returns(Task.FromResult(new ResourceResponse<Document>(document)));
The ResourceResponse class has the constructor that contains the DocumentServiceResponse parameter marked as internal.
This is bad because even though you can create a ResourceReponse object from your DTO class you cannot set things like RUs consumed, response code and pretty much anything else because they are all coming from the ResourceResponseBase which also has the DocumentServiceResponse marked as internal.
Please find code at below link
how-to-mock-or-instantiate
Kinda late but with Microsoft.Azure.DocumentDB.Core 2.4.2 there's a DocumentClient constructor that accepts an HttpMessageHandler as a parameter. It's ugly (so much so it deserves a downvote) but you can use this to inject responses with status codes. As far as I can tell nothing's leaving my box when I do this.
I also had to create a test-only constructor since I would never want to use this during running code. But for anyone still interested until a better library comes out here are the relevant parts.
Create your client
var client = new DocumentClient(host, authText, handler);
In your tests you can use a mocked handler like this:
public static Mock<HttpMessageHandler> CreateHttpMessageHandler(List<HttpResponseMessage> responses)
{
var handlerMock = new Mock<HttpMessageHandler>(MockBehavior.Strict);
handlerMock.Protected()
.Setup<Task<HttpResponseMessage>>(
nameof(HttpClient.SendAsync),
ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>())
.ReturnsAsync(() => {
var response = responses[0];
responses.RemoveAt(0);
return response;
})
.Verifiable();
return handlerMock;
}
I created this response factory simulator
private HttpResponseMessage Respond(string text)
{
var response = new HttpResponseMessage(HttpStatusCode.OK)
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(text),
};
return response;
}
and set up the handler with something like this:
var responses = new List<HttpResponseMessage> {
Respond("{ ... }"),
Respond("{ ... }"),
Respond("{ ... }"),
Respond("{ ... }"),
};
Replace the ... with your Fiddler (or similar) trace output from an actual call to your CosmosDB. FWIW I had to supply 2 copies of my actual payload as the final 2 responses. This is obviously AS-IS and SUBJECT TO CHANGE but It worked for me. Hope it helps you and looking forward to a modern library designed to interfaces with SOLID principles.
I am using RestKit from an iOS app to connect to a Web API service that we are building in C# .Net 4.
I am having the same issue from here: RestKit non-kvc object mapping
Basically C# returns something like:
formatted raw
BODY
[
{
"Id":6,
"Guid":"00000000-0000-0000-0000-000000000000",
"Owner":null,
"Message":"Testing Wom#10",
"HashTags":null,
"createdtime":"2012-10-28T00:00:00",
"PlayedCount":100,
"DurationInSecs":150.0,
"FileSizeInBytes":20000,
"FileUrl":"http://www.wom.com"
}
]
While the standard format expected by RestKit is
{"woms": [
{
"Id":6,
"Guid":"00000000-0000-0000-0000-000000000000",
"Owner":null,
"Message":"Testing Wom#10",
"HashTags":null,
"createdtime":"2012-10-28T00:00:00",
"PlayedCount":100,
"DurationInSecs":150.0,
"FileSizeInBytes":20000,
"FileUrl":"http://www.wom.com"
}
]
I don't care using a way or another, however, it seems that it would be easier from the iOS side to make C# return the "customers" class name.
How can I tell C# to return that?
Thanks.
This is the current code in my ApiController in C#:
namespace WomWeb.Controllers.Apis
{
[Authorize]
public class WomsController : ApiController
{
private WomContext db = new WomContext();
// GET api/Woms
public IEnumerable<Wom> GetWoms()
{
return db.Woms.AsEnumerable();
}
I've had some issues like this when trying to serialize JSON in C#. I think the easiest way is wrap the customer in another class. If you only need to serialize in one place you can do something like var temp = new Object { customer customer = new customer(); } right before making the call to serialize it.
This is the best solution I have found so far. Basically replace the IEnumerable by HttpResponseMessage and use the Request.CreateResponse to respond (code below).
While it works it is less than ideal: I lose the abstraction, and now the controller respond with Json regardless of the request headers (that logic was resolved automatically, but when using the CreateResponse I am writing directly to the output).
// GET api/Woms
//public IEnumerable<Wom> GetWoms()
public HttpResponseMessage GetWoms()
{
//return db.Woms.Include("Owner").AsEnumerable();
return Request.CreateResponse(HttpStatusCode.OK, new { woms = Include("Owner").AsEnumerable() });
}
I like a lot how the HttpClient is architectured - but I can't figure out how to add a "not quite standard" media type to be handled by the XmlSerializer.
This code:
var cli = new HttpClient();
cli
.GetAsync("http://stackoverflow.com/feeds/tag?tagnames=delphi&sort=newest")
.ContinueWith(task =>
{
task.Result.Content.ReadAsAsync<Feed>();
});
works fine when pointed to atom feeds that have Content-Type of "text/xml", but the one in the example fails with the "No 'MediaTypeFormatter' is available to read an object of type 'Feed' with the media type 'application/atom+xml'" message.
I tried different combinations of specifying MediaRangeMappings for the XmlMediaTypeFormatter (to be passed as an argument to ReadAsAsync) but with no success.
What is the "recommended" way to configure the HttpClient to map "application/atom+xml" and "application/rss+xml" to XmlSerializer?
Here is the code that works (credits to ASP.net forum thread):
public class AtomFormatter : XmlMediaTypeFormatter
{
public AtomFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/atom+xml"));
}
protected override bool CanReadType(Type type)
{
return base.CanReadType(type) || type == typeof(Feed);
}
}
var cli = new HttpClient();
cli
.GetAsync("http://stackoverflow.com/feeds/tag?tagnames=delphi&sort=newest")
.ContinueWith(task =>
{
task.Result.Content.ReadAsAsync<Feed>(new[] { new AtomFormatter });
});
Still, would like to see a solution without subclassing XmlMediaTypeFormatter - anybody?
The problem is that you are trying to convert the result straight to Feed. As error is clearly saying, it cannot figure our how to convert the application/atom+xml into Feed.
You would have to perhaps return as XML and then use and XmlReader to initialise your Feed.
Alternative is to provide your own media formatter - and implementation which encapsulates this.