I need to make the following call to an open API (https://www.openfigi.com/api)
Curl Example:
curl -v -X POST 'https://api.openfigi.com/v1/mapping' \
--header 'Content-Type: text/json' \
--data '[{"idType":"ID_WERTPAPIER","idValue":"851399","exchCode":"US"}]'
Request Format
The request is passed in via HTTP request body. The only supported HTTP verb is POST. Here is a sample request to the API:
[
{"idType":"ID_ISIN","idValue":"US4592001014"},
{"idType":"ID_WERTPAPIER","idValue":"851399","exchCode":"US"},
{"idType":"ID_BB_UNIQUE","idValue":"EQ0010080100001000","currency": "USD"},
{"idType":"ID_SEDOL","idValue":"2005973","micCode":"EDGX", "currency":"USD"}
]
Using ServiceStack Request DTO, how do I make a RequestDto to achieve a call to to the above third party service endpoint.
This is just an exercise of creating DTOs which match the shape of the JSON you want to output and JSON you want to receive. To emit the exact the exact JSON property names you can either use [DataMember] on the Request DTO, or JsConfig.EmitCamelCaseNames = true to tell ServiceStack to serialize properties in camelCase or you can use JsConfig.With() to create a Custom Scope.
I've created a Live example of this in Gistlyn which you can use to experiment against Bloomberg's API.
I've used [DataMember] attribute here as it will work independent of your Json Serialization config. You don't need to do this for the Response DTO because ServiceStack Serializers is case-insensitive.
So to send the Request that matches the shape of that JSON you can use:
[DataContract]
public class Mapping
{
[DataMember(Name="idType")]
public string IdType { get; set; }
[DataMember(Name="idValue")]
public string IdValue { get; set; }
[DataMember(Name="exchCode")]
public string ExchCode { get; set; }
[DataMember(Name="currency")]
public string Currency { get; set; }
[DataMember(Name="micCode")]
public string MicCode { get; set; }
}
You can use ServiceStack's HTTP Utils to easily send requests to 3rd Party APIs, e.g:
var url = "https://api.openfigi.com/v1/mapping";
var json = url.PostJsonToUrl(new[]{
new Mapping { IdType = "ID_ISIN", IdValue = "US4592001014" },
new Mapping { IdType = "ID_WERTPAPIER", IdValue = "851399", ExchCode = "US" },
new Mapping { IdType = "ID_BB_UNIQUE", IdValue = "EQ0010080100001000", Currency = "USD" },
new Mapping { IdType = "ID_SEDOL", IdValue = "2005973", MicCode = "EDGX", Currency = "USD" },
});
Then to receive the response you need to create DTOs which match the shape of the JSON Response which looks like:
public class BloombertResult
{
public string Figi { get; set; }
public string SecurityType { get; set; }
public string MarketSector { get; set; }
public string Ticker { get; set; }
public string Name { get; set; }
public string UniqueId { get; set; }
public string ExchCode { get; set; }
public string ShareClassFIGI { get; set; }
public string CompositeFIGI { get; set; }
public string SecurityType2 { get; set; }
public string SecurityDescription { get; set; }
public string UniqueIdFutOpt { get; set; }
}
public class BloombergResponse
{
public List<BloombertResult> Data { get; set; }
public string Error { get; set; }
}
Which you can just deserialize into a collection of BloombergResponse, e.g:
var response = json.FromJson<BloombergResponse[]>();
Gistlyn will show you a nice human readable preview of each variable by clicking on it in the watch window. Or if you're this in a C# Unit test you can quickly see to populated DTOs with:
response.PrintDump();
Related
I am trying to patch a object with the following code.
public object Patch(EditBlog request)
{
using (var db = _db.Open())
{
try
{
request.DateUpdated = DateTime.Now;
Db.Update<Blog>(request, x => x.Id == request.Id);
return new BlogResponse { Blog = Blog = Db.Select<Blog>(X=>X.Id == request.Id).SingleOrDefault()};
}
catch (Exception e)
{
return HttpError.Conflict("Something went wrong");
}
}
}
In Postman, I am calling the function like this "api/blog/1?=Title=Test1&Summary=Test&UserId=1".
When debugging I can see that those values has been assigned to the request.
During the Update it throws: "Cannot update identity column 'Id'"
My model looks like this
public class Blog
{
[AutoIncrement]
public int Id { get; set; }
public IUserAuth User { get; set; }
[Required]
public int UserId { get; set; }
[Required]
public string Title { get; set; }
public string Summary { get; set; }
public string CompleteText { get; set; }
[Required]
public DateTime DateAdded { get; set; }
public DateTime DateUpdated { get; set; }
}
And the EditBlog DTO looks like this:
[Route("/api/blog/{id}", "PATCH")]
public class EditBlog : IReturn<BlogResponse>
{
public int Id { get; set; }
public IUserAuth User { get; set; }
public int UserId { get; set; }
public string Title { get; set; }
public string Summary { get; set; }
public string CompleteText { get; set; }
public DateTime DateUpdated { get; set; }
}
The error message "Cannot update identity column 'Id'" does not exist anywhere in ServiceStack.OrmLite, it could be an error returned by the RDBMS when you're trying to update the Primary Key which OrmLite wouldn't do when updating a Model annotated with a Primary Key like your Blog class has with its annotated [AutoIncrement] Id Primary Key.
The error is within your Db.Up<T> method that's performing the update, which is not an OrmLite API, so it's likely your own custom extension method or an alternative library.
I would implement a PATCH Request in OrmLite with something like:
var blog = request.ConvertTo<Blog>();
blog.DateUpdated = DateTime.Now;
Db.UpdateNonDefaults(blog);
i.e. using OrmLite's UpdateNonDefaults API to only update non default fields and updating using the Blog Table POCO not the EditBlog Request DTO.
Also you should use the Single APIs when fetching a single record, e.g:
Blog = Db.SingleById<Blog>(request.Id)
or
Blog = Db.Single<Blog>(x => x.Id == request.Id)
Instead of:
Blog = Db.Select<Blog>(X=>X.Id == request.Id).SingleOrDefault()
ServiceStack's AutoQuery Viewer Plugin allows you to decorate the AutoQueries using AutoQuery metadata attributes. I use the existing Metadata service in AutoQuery to power a front-end and display search queries (similar to the existing AutoQuery Admin Feature)
How can I extend/ add additional properties to the AutoQueryViewerAttribute, such that they are available in the Autoquery metadata service?
Current list of AutoQuery attributes available:
public class AutoQueryViewerAttribute : AttributeBase
{
public string Title { get; set; }
public string Description { get; set; }
public string IconUrl { get; set; }
public string BrandUrl { get; set; }
public string BrandImageUrl { get; set; }
public string TextColor { get; set; }
public string LinkColor { get; set; }
public string BackgroundColor { get; set; }
public string BackgroundImageUrl { get; set; }
public string DefaultSearchField { get; set; }
public string DefaultSearchType { get; set; }
public string DefaultSearchText { get; set; }
public string DefaultFields { get; set; }
}
I would like to extend the list of AutoQueryViewerAttribute attributes and add two additional properties:
public string SourceDescription { get; set; }
public string SourceApplicationName { get; set; }
You can't extend the [AutoQueryViewer] attribute which is hard coded. The Info on the Attribute is used to populate the Typed AutoQueryMetadataResponse DTO which is what's serialized to provide the AutoQuery metadata services. I've just added Meta String Dictionaries on the MetadataType, AutoQueryViewerConfig, AutoQueryViewerUserInfo, AutoQueryOperation and AutoQueryMetadataResponse DTO in this commit so you can attach additional metadata to the AutoQuery metadata DTOs using the MetadataFilter, e.g:
Plugins.Add(new AutoQueryMetadataFeature {
MetadataFilter = response => {
response.Meta = new Dictionary<string,string> {
{ "SourceApplicationName", "My App" },
{ "SourceDescription", "My App Description" },
};
}
});
This change is available from v4.5.13 that's now available on MyGet.
I've subscribed to the Nexmo SMS service and they offer a callback URL for inbound SMS. The post request gives the following Json structure when notifying of SMS receipt:
{
"msisdn": "441632960960",
"to": "441632960961",
"messageId": "02000000E68951D8",
"text": "Hello7",
"type": "text",
"keyword": "HELLO7",
"message-timestamp": "2016-07-05 21:46:15"
}
Using the following code snippet, I can map all of the fields to my SmsReceipt apart from 'message-timestamp'. None of the message timestamp fields are populated.
public class SmsReceipt
{
public string msisdn { get; set; }
public string to { get; set; }
public string messageId { get; set; }
public string text { get; set; }
public string type { get; set; }
public string keyword { get; set; }
public string messagetimestamp { get; set; }
public string messageTimestamp { get; set; }
public string message_timestamp { get; set; }
}
[HttpPost("inboundsms")]
public async Task<IActionResult> Post([FromBody] SmsReceipt receipt)
{
return StatusCode(200);
}
I guess the same applies to incoming requests with other special characters such as '.' Any ideas greatly appreciated.
Your property name should match with the property name in the data being sent. Looks like your payload property name is message-timestamp. You cannot create a C# property with a - in it. So your options are
Either update your json payload property to match with one from your C# class.
Decorate your C# class with JsonProperty(From Newtonsoft.Json) where you specify what property from the posted data should be mapped to this property.
Also i suggest use the DateTime type. That type was created to deal with date time value.
public class SmsReceipt
{
public string Msisdn { get; set; }
public string To { get; set; }
public string MessageId { get; set; }
public string Text { get; set; }
public string Type { get; set; }
public string Keyword { get; set; }
[JsonProperty("message-timestamp")]
public DateTime Messagetimestamp { get; set; }
}
I'm having an issue with my ServiceStack w/ Swagger implementation regarding documenting required/optional properties. Developers implementing clients that consume my services love the Swagger documentation, however they don't know which properties are required vs. optional--aside from getting a 400 response on each attempt to get a valid request through.
Take the following example:
public class UserProfile
{
public string FirstName { get; set; }
public string LastName { get; set; }
public UserAddress Address { get; set; }
}
public class UserAddress
{
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
public string Country { get; set; }
public string PhoneNumber { get; set; }
}
Swagger will cleanly show both of these types if they are part of my DTO, however I can't convey that FirstName, LastName, or any of the Address properties are required or not. Is there a way to accomplish this without having to roll a separate spec document?
You can use an [ApiMember(IsRequired = false)] attribute on the properties in the DTO to add extra information for swagger ui.
There is list of the attributes that swagger ui will recognise on the servicestack wiki
I am writing a helloworld MonoTouch App to use ServiceStack to consume Json and have a two part related question.
My test json is: https://raw.github.com/currencybot/open-exchange-rates/master/latest.json
In my DTO object how to I use different named properties that map to json elements?
I have this, and it works, but I want to use different field names?
public class Currency
{
public string disclaimer { get; set; }
public string license { get; set; }
public string timestamp { get; set; }
}
And how do I add the Rates collection in my DTO from this json?
"rates": {
"AED": 3.6731,
"AFN": 48.330002,
"ALL": 103.809998,
ETC...
ServiceStack has an awesome Fluent JSON Parser API that makes it really easy to work against your existing model without having to use the "Contract" base serialization. This should get you started:
public class Rates {
public double AED { get; set; }
public double AFN { get; set; }
public double ALL { get; set; }
}
public class Currency {
public string disclaimer { get; set; }
public string license { get; set; }
public string timestamp { get; set; }
public Rates CurrencyRates { get; set; }
}
...
var currency = new Currency();
currency.CurrencyRates = JsonObject.Parse(json).ConvertTo(x => new Currency{
disclaimer = x.Get("disclaimer"),
license = x.Get("license"),
timestamp = x.Get("timestamp"),
CurrencyRates = x.Object("rates").ConvertTo(r => new Rates {
AED = x.Get<double>("AED"),
AFN = x.Get<double>("AFN"),
ALL = x.Get<double>("ALL"),
})
});