Microsoft Azure Text Translator - Subscription Key Not Working - c#

I am trying to build a basic text translator in console using Microsoft Azure's Text Translator. However, my subscription keys are simply not working. I have generated them multiple times, as well as inputted them manually. Please assist. I have left in the keys for further clarification. Thank you for reading, and for your help.
The code generates this error:
if (null == subscriptionKey)
{
throw new Exception("Please set/export the environment variable: " + key_var);
// This sample requires C# 7.1 or later for async/await.
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
// Install Newtonsoft.Json with NuGet
using Newtonsoft.Json;
namespace TranslateTextSample
{
/// <summary>
/// The C# classes that represents the JSON returned by the Translator Text API.
/// </summary>
public class TranslationResult
{
public DetectedLanguage DetectedLanguage { get; set; }
public TextResult SourceText { get; set; }
public Translation[] Translations { get; set; }
}
public class DetectedLanguage
{
public string Language { get; set; }
public float Score { get; set; }
}
public class TextResult
{
public string Text { get; set; }
public string Script { get; set; }
}
public class Translation
{
public string Text { get; set; }
public TextResult Transliteration { get; set; }
public string To { get; set; }
public Alignment Alignment { get; set; }
public SentenceLength SentLen { get; set; }
}
public class Alignment
{
public string Proj { get; set; }
}
public class SentenceLength
{
public int[] SrcSentLen { get; set; }
public int[] TransSentLen { get; set; }
}
class Program
{
private const string key_var="b1f43a68dce24b0280360691ad68bc75";
private static readonly string subscriptionKey = Environment.GetEnvironmentVariable(key_var);
private const string endpoint_var = "https://consoletexttranslator.cognitiveservices.azure.com/sts/v1.0/issuetoken";
private static readonly string endpoint = Environment.GetEnvironmentVariable(endpoint_var);
static Program()
{
if (null == subscriptionKey)
{
throw new Exception("Please set/export the environment variable: " + key_var);
}
if (null == endpoint)
{
throw new Exception("Please set/export the environment variable: " + endpoint_var);
}
}
// Async call to the Translator Text API
static public async Task TranslateTextRequest(string subscriptionKey, string endpoint, string route, string inputText)
{
object[] body = new object[] { new { Text = inputText } };
var requestBody = JsonConvert.SerializeObject(body);
using (var client = new HttpClient())
using (var request = new HttpRequestMessage())
{
// Build the request.
request.Method = HttpMethod.Post;
request.RequestUri = new Uri(endpoint + route);
request.Content = new StringContent(requestBody, Encoding.UTF8, "application/json");
request.Headers.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
// Send the request and get response.
HttpResponseMessage response = await client.SendAsync(request).ConfigureAwait(false);
// Read response as a string.
string result = await response.Content.ReadAsStringAsync();
TranslationResult[] deserializedOutput = JsonConvert.DeserializeObject<TranslationResult[]>(result);
// Iterate over the deserialized results.
foreach (TranslationResult o in deserializedOutput)
{
// Print the detected input languge and confidence score.
Console.WriteLine("Detected input language: {0}\nConfidence score: {1}\n", o.DetectedLanguage.Language, o.DetectedLanguage.Score);
// Iterate over the results and print each translation.
foreach (Translation t in o.Translations)
{
Console.WriteLine("Translated to {0}: {1}", t.To, t.Text);
}
}
}
}
static async Task Main(string[] args)
{
// This is our main function.
// Output languages are defined in the route.
// For a complete list of options, see API reference.
// https://learn.microsoft.com/azure/cognitive-services/translator/reference/v3-0-translate
string route = "/translate?api-version=3.0&to=de&to=it&to=ja&to=th";
// Prompts you for text to translate. If you'd prefer, you can
// provide a string as textToTranslate.
Console.Write("Type the phrase you'd like to translate? ");
string textToTranslate = "Hello, Tommy.";
await TranslateTextRequest(subscriptionKey, endpoint, route, textToTranslate);
Console.WriteLine("Press any key to continue.");
Console.ReadKey();
}
}
}

pls try the code below , it works for me :
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
// Install Newtonsoft.Json with NuGet
using Newtonsoft.Json;
namespace TranslateTextSample
{
/// <summary>
/// The C# classes that represents the JSON returned by the Translator Text API.
/// </summary>
public class TranslationResult
{
public DetectedLanguage DetectedLanguage { get; set; }
public TextResult SourceText { get; set; }
public Translation[] Translations { get; set; }
}
public class DetectedLanguage
{
public string Language { get; set; }
public float Score { get; set; }
}
public class TextResult
{
public string Text { get; set; }
public string Script { get; set; }
}
public class Translation
{
public string Text { get; set; }
public TextResult Transliteration { get; set; }
public string To { get; set; }
public Alignment Alignment { get; set; }
public SentenceLength SentLen { get; set; }
}
public class Alignment
{
public string Proj { get; set; }
}
public class SentenceLength
{
public int[] SrcSentLen { get; set; }
public int[] TransSentLen { get; set; }
}
class Program
{
private const string subscriptionKey = "<your translator API key>";
private const string endpoint = "https://api.cognitive.microsofttranslator.com";
static Program()
{
if (null == subscriptionKey)
{
throw new Exception("Please set/export the environment variable: " + subscriptionKey);
}
if (null == endpoint)
{
throw new Exception("Please set/export the environment variable: " + endpoint);
}
}
// Async call to the Translator Text API
static public async Task TranslateTextRequest(string subscriptionKey, string endpoint, string route, string inputText)
{
object[] body = new object[] { new { Text = inputText } };
var requestBody = JsonConvert.SerializeObject(body);
using (var client = new HttpClient())
using (var request = new HttpRequestMessage())
{
// Build the request.
request.Method = HttpMethod.Post;
request.RequestUri = new Uri(endpoint + route);
request.Content = new StringContent(requestBody, Encoding.UTF8, "application/json");
request.Headers.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
// Send the request and get response.
HttpResponseMessage response = await client.SendAsync(request).ConfigureAwait(false);
// Read response as a string.
string result = await response.Content.ReadAsStringAsync();
TranslationResult[] deserializedOutput = JsonConvert.DeserializeObject<TranslationResult[]>(result);
// Iterate over the deserialized results.
foreach (TranslationResult o in deserializedOutput)
{
// Print the detected input languge and confidence score.
Console.WriteLine("Detected input language: {0}\nConfidence score: {1}\n", o.DetectedLanguage.Language, o.DetectedLanguage.Score);
// Iterate over the results and print each translation.
foreach (Translation t in o.Translations)
{
Console.WriteLine("Translated to {0}: {1}", t.To, t.Text);
}
}
}
}
static void Main(string[] args)
{
MainAsync(args).GetAwaiter().GetResult();
Console.ReadKey();
Console.WriteLine("press anykey to exit");
}
static async Task MainAsync(string[] args)
{
string route = "/translate?api-version=3.0&to=de&to=it&to=ja&to=th";
// Prompts you for text to translate. If you'd prefer, you can
// provide a string as textToTranslate.
string textToTranslate = "Hello, Tommy.";
await TranslateTextRequest(subscriptionKey, endpoint, route, textToTranslate);
}
}
}
before you run this console app, pls replace the value of "subscriptionKey" with your own key value here :
Result :
If there is anything unclear , pls feel free to let me know : )

Related

JSON string will not deserialize into the type specified

I have the following bit of code whihc sends a Http POST request to the server. The server reurns a 400 Bad request response along with a error object in the form of Json:
namespace MyApp.Shared.Dtos.Response
{
public class ErrorItem
{
public string Message { get; set; }
public string Tag { get; set; }
}
public class ErrorDto
{
public string Title { get; set; }
public List<ErrorItem> Errors { get; set; } = new();
}
}
namespace Accounting.Web.Services
{
public interface IHttpService
{
Task<T> Get<T>(string uri);
Task<T> Post<T>(string uri, object value, bool addBearerToken = false);
public ErrorDto Error { get; set; }
}
public class HttpService: IHttpService
{
private HttpClient _httpClient;
public ErrorDto Error { get; set; }
public HttpService(HttpClient httpClient)
{
_httpClient = httpClient;
_stateService = stateService;
}
public async Task<T> Post<T>(string uri, object value)
{
var request = new HttpRequestMessage(HttpMethod.Post, uri);
request.Content = new StringContent(JsonSerializer.Serialize(value), Encoding.UTF8, "application/json");
return await sendRequest<T>(request, addBearerToken);
}
private async Task<T> sendRequest<T>(HttpRequestMessage request)
{
using var response = await _httpClient.SendAsync(request);
if (response.StatusCode == System.Net.HttpStatusCode.BadRequest)
{
var result = await response.Content.ReadAsStringAsync();
Error = JsonSerializer.Deserialize<ErrorDto>(result);
//..
}
else
{
//..
}
}
}
}
The result correctly recieves the following response from the server as a JSON string:
{"title":"Username or password is incorrect","errors":[]}
And I can confirm by inspecting var result, it has the above value.
However, It doesn't seem deserialize into the ErrorDto class as one would expect it to:
Error = JsonSerializer.Deserialize(result);
But I simply cannot see any problems with the code, it looks like it should be working.
*** UPDATE ***
My server API code returrns the JSOn using the same DTO class (It's a shared class) using the following code:
[HttpPost("authenticate")]
public ActionResult Authenticate(AuthenticateRequest loginRequest)
{
var auth = _userService.Authenticate(loginRequest);
ErrorDto error = new()
{
Title = "Username or password is incorrect"
};
if (auth.user == null || auth.token == null)
{
return BadRequest(error);
}
return Ok(auth.user.ConvertToDto(auth.token));
}
By default System.Text.Json is case-sensitive. There are multiple options to handle this, for example by providing corresponding JsonSerializerOptions:
var json = #"{""title"":""Username or password is incorrect"",""errors"":[]}";
var errorDto = JsonSerializer.Deserialize<ErrorDto>(json, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
Or marking properties with corresponding JsonPropertyNameAttribute:
public class ErrorItem
{
[JsonPropertyName("message")]
public string Message { get; set; }
[JsonPropertyName("tag")]
public string Tag { get; set; }
}
public class ErrorDto
{
[JsonPropertyName("title")]
public string Title { get; set; }
[JsonPropertyName("errors")]
public List<ErrorItem> Errors { get; set; } = new();
}
UPD
From How to customize property names and values with System.Text.Json doc:
Note
The web default is camel case.
If you want to switch from camel case to the naming policy used for DTOs you can do the following:
builder.Services.AddControllers()
.AddJsonOptions(opts => opts.JsonSerializerOptions.PropertyNamingPolicy = null);

ASP.NET Core Web API submit form has file and text fields error

I am using .NET 5.0.100-preview.8.20417.9, ASP.NET Core 5 Web API, Entity Framework Core 5, SQL Server 2019, Postman v7.32.0.
model
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace shadow.DTO
{
public partial class TrustedPersonUserDTO
{
public string Fullname { get; set; }
public string AliasName { get; set; }
public string Email { get; set; }
public string PhoneNumber1 { get; set; }
public string PhoneNumber2 { get; set; }
public string PhoneNumber3 { get; set; }
public int? RelationshipId { get; set; }
public string About { get; set; }
public int? AvatarId { get; set; }
public DateTime? Created { get; set; }
public DateTime? Modified { get; set; }
// Id của user.
public string UserId { get; set; }
}
public partial class TrustedPersonUserDTO2
{
public string Fullname { get; set; }
public string AliasName { get; set; }
public string Email { get; set; }
public string PhoneNumber1 { get; set; }
public string PhoneNumber2 { get; set; }
public string PhoneNumber3 { get; set; }
public int? RelationshipId { get; set; }
public string About { get; set; }
public int? AvatarId { get; set; }
public DateTime? Created { get; set; }
public DateTime? Modified { get; set; }
// Id của user.
public string UserId { get; set; }
public IFormFile file { get; set; }
}
}
and controller
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using shadow.Data;
using shadow.DTO;
using shadow.Models;
using shadow.Services;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace shadow.Controllers
{
[Route("[controller]")]
[ApiController]
public class UserTrustedPersonController : ControllerBase
{
private IUserService _userService;
private IMailService _mailService;
private IConfiguration _configuration;
private ApplicationDbContext _db;
public static IWebHostEnvironment _environment;
public UserTrustedPersonController(IUserService userService, IMailService mailService, IConfiguration configuration, ApplicationDbContext db, IWebHostEnvironment environment)
{
_userService = userService;
_mailService = mailService;
_configuration = configuration;
_db = db;
_environment = environment;
}
/// <summary>
/// Thêm mới người ủy thác kèm Relationship.
/// </summary>
/// <param name="trustedPersonUserDTO"></param>
/// <returns></returns>
[HttpPost]
[Authorize]
public async Task<ActionResult<TrustedPersonUserDTO>> AddUserTrustedPersons(TrustedPersonUserDTO trustedPersonUserDTO)
{
var item = new TrustedPerson
{
Fullname = trustedPersonUserDTO.Fullname,
About = trustedPersonUserDTO.About,
AliasName = trustedPersonUserDTO.AliasName,
AvatarId = trustedPersonUserDTO.AvatarId,
Created = DateTime.Now,
Email = trustedPersonUserDTO.Email,
PhoneNumber1 = trustedPersonUserDTO.PhoneNumber1,
PhoneNumber2 = trustedPersonUserDTO.PhoneNumber2,
PhoneNumber3 = trustedPersonUserDTO.PhoneNumber3,
RelationshipId = trustedPersonUserDTO.RelationshipId
};
_db.TrustedPeople.Add(item);
await _db.SaveChangesAsync();
UserTrustedPerson userTrustedPerson = new UserTrustedPerson();
userTrustedPerson.UserId = trustedPersonUserDTO.UserId;
userTrustedPerson.TrustedPersonId = item.Id;
_db.UserTrustedPeople.Add(userTrustedPerson);
await _db.SaveChangesAsync();
return Ok(userTrustedPerson);
}
/// <summary>
/// Thêm mới người ủy thác kèm Relationship.
/// </summary>
/// <param name="trustedPersonUserDTO"></param>
/// <returns></returns>
[HttpPost]
[Route("add")]
[Authorize]
public async Task<ActionResult<TrustedPersonUserDTO>> AddUserTrustedPersons2(TrustedPersonUserDTO2 trustedPersonUserDTO)
{
var item = new TrustedPerson
{
Fullname = trustedPersonUserDTO.Fullname,
About = trustedPersonUserDTO.About,
AliasName = trustedPersonUserDTO.AliasName,
AvatarId = trustedPersonUserDTO.AvatarId,
Created = DateTime.Now,
Email = trustedPersonUserDTO.Email,
PhoneNumber1 = trustedPersonUserDTO.PhoneNumber1,
PhoneNumber2 = trustedPersonUserDTO.PhoneNumber2,
PhoneNumber3 = trustedPersonUserDTO.PhoneNumber3,
RelationshipId = trustedPersonUserDTO.RelationshipId
};
_db.TrustedPeople.Add(item);
await _db.SaveChangesAsync();
await WriteFile(trustedPersonUserDTO.file);
UserTrustedPerson userTrustedPerson = new UserTrustedPerson();
userTrustedPerson.UserId = trustedPersonUserDTO.UserId;
userTrustedPerson.TrustedPersonId = item.Id;
_db.UserTrustedPeople.Add(userTrustedPerson);
await _db.SaveChangesAsync();
return Ok(userTrustedPerson);
}
public class FileUploadAPI
{
public IFormFile files { get; set; }
}
[HttpPost]
[Route("upload2")]
[Obsolete]
public async Task<string> Post(FileUploadAPI objFile)
{
try
{
if (objFile.files.Length > 0)
{
if (!Directory.Exists(_environment.WebRootPath + "\\Upload\\"))
{
Directory.CreateDirectory(_environment.WebRootPath + "\\Upload\\");
}
using (FileStream fileStream = System.IO.File.Create(_environment.WebRootPath + "\\Upload\\" + objFile.files.FileName))
{
objFile.files.CopyTo(fileStream);
fileStream.Flush();
return "\\Upload\\" + objFile.files.FileName;
}
}
else
{
return "Failed";
}
}
catch (Exception ex)
{
return ex.Message.ToString();
}
}
// Upload file ảnh.
[HttpPost("upload", Name = "upload")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(typeof(string), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> UploadFile(IFormFile file, CancellationToken cancellationToken)
{
if (CheckIfExcelFile(file))
{
await WriteFile(file);
}
else
{
return BadRequest(new { message = "Invalid file extension" });
}
return Ok();
}
/// <summary>
/// Method to check if file is excel file
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
private bool CheckIfExcelFile(IFormFile file)
{
var extension = "." + file.FileName.Split('.')[file.FileName.Split('.').Length - 1];
return (extension == ".png" || extension == ".jpg" || extension == ".bmp" || extension == ".gif" || extension == ".tif"); // Change the extension based on your need
}
private async Task<bool> WriteFile(IFormFile file)
{
bool isSaveSuccess = false;
string fileName;
try
{
var extension = "." + file.FileName.Split('.')[file.FileName.Split('.').Length - 1];
fileName = DateTime.Now.Ticks + extension; //Create a new Name for the file due to security reasons.
var pathBuilt = Path.Combine(Directory.GetCurrentDirectory(), "Upload\\files");
if (!Directory.Exists(pathBuilt))
{
Directory.CreateDirectory(pathBuilt);
}
var path = Path.Combine(Directory.GetCurrentDirectory(), "Upload\\files", fileName);
using (var stream = new FileStream(path, FileMode.Create))
{
await file.CopyToAsync(stream);
}
isSaveSuccess = true;
}
catch (Exception e)
{
//log error
}
return isSaveSuccess;
}
}
}
I call POST
http://localhost:5002/UserTrustedPerson/add
error
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.13",
"title": "Unsupported Media Type",
"status": 415,
"traceId": "00-a1fc92edfaf6884d8d74e30c21090e87-7acaa91089108e49-00"
}
How to call POST RESTful API has file and text fields success?
You can set
[DataType(DataType.Upload)] public IFormFile file{ get; set; }
In you Model
As #Purushothaman suggested adding [FromForm] is a valid and easy solution just as long as you know what you are doing. If your specification says you want the endpoint to accept multipart/form-data otherwise I'd opt for endpoint using application/json.
Keep in mind most API operate on application/json not form data. This might cause some integration issues when using form-data.
Why Postman requests with valid Contant Type headers doesn't work?
It doesn't matter that you set application/json as it's being overwritten. As per documentation form-data and documentation auto-generated-headers. So the Content-type header you are sending is Content Type multipart/form-data not application/json and that causes 415 response.
How to make POST API requests with Postman
If you don't want to use [FormData] and recompile server code, it's not difficult to change the settings in Postman.
First go to the body inside your POST request, find the raw option and select JSON (application/json) drop down next to it on the right. Paste your data in json format.

Deserialize Json C# error

Well, I'm new to programming, and I have a problem.
This is my class Valores
public class Valores
{
[JsonProperty("nome")]
public string Nome { get; set; }
[JsonProperty("valor")]
public double Valor { get; set; }
[JsonProperty("ultima_consulta")]
public int UltimaConsulta { get; set; }
[JsonProperty("fonte")]
public string Fonte { get; set; }
}
And this is my method where I get and deserialize my Json
public static async Task<Valores> GetAsync()
{
Valores valores = null;
using (var client = new HttpClient())
{
var json = await client.GetStringAsync("http://api.promasters.net.br/cotacao/v1/valores");
valores = JsonConvert.DeserializeObject<Valores>(json);
}
return valores;
}
This is json that the way: "http://api.promasters.net.br/cotacao/v1/valores" returns.
{
"status": true,
"valores": {
"USD": {
"nome": "Dólar",
"valor": 3.0717,
"ultima_consulta": 1490040302,
"fonte": "UOL Economia - http://economia.uol.com.br/"
},
"EUR": {
"nome": "Euro",
"valor": 3.3002,
"ultima_consulta": 1490040302,
"fonte": "UOL Economia - http://economia.uol.com.br/"
},
"ARS": {
"nome": "Peso Argentino",
"valor": 0.1965,
"ultima_consulta": 1490040302,
"fonte": "UOL Economia - http://economia.uol.com.br/"
},
"GBP": {
"nome": "Libra Esterlina",
"valor": 3.7966,
"ultima_consulta": 1490040302,
"fonte": "UOL Economia - http://economia.uol.com.br/"
},
"BTC": {
"nome": "Bitcoin",
"valor": 3472,
"ultima_consulta": 1490067603,
"fonte": "Mercado Bitcoin - http://www.mercadobitcoin.com.br/"
}
}
}
I do not know what I did wrong, because this
var json = await client.GetStringAsync("http://api.promasters.net.br/cotacao/v1/valores");
It was to receive Json in string, but is not receiving anything, it's like an empty string.
I experimented a bit, and it appears the web site requires the user agent request string to be set to something in order for JSON to be returned. And, by something, I mean that the string "something" seems to work, as does the string "Wget/1.11.4". You should check the documentation (Portugese) to make sure there are no restrictions on programmatic access to this site, and comply with those access restrictions (if any).
Also, your data model does not reflect your JSON. You need a higher level root object as follows:
public class RootObject
{
public RootObject() { this.valores = new Dictionary<string, Valores>(); }
public bool status { get; set; }
public Dictionary<string, Valores> valores { get; set; }
}
Here is a sample fiddle that successfully downloads and deserializes JSON from the site by setting the user agent. It uses WebClient since that's what seems to be available on https://dotnetfiddle.net/:
public static async Task<RootObject> GetAsync()
{
using (var client = new WebClient())
{
client.Headers["User-Agent"] = "something";
var json = await client.DownloadStringTaskAsync(#"http://api.promasters.net.br/cotacao/v1/valores");
var root = JsonConvert.DeserializeObject<RootObject>(json);
return root;
}
}
And for HttpClient I think it should be (untested):
public static async Task<RootObject> GetAsync()
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("User-Agent", "something");
var json = await client.GetStringAsync("http://api.promasters.net.br/cotacao/v1/valores");
return JsonConvert.DeserializeObject<RootObject>(json);
}
See also this post for a discussion of whether to dispose the HttpClient.
There issue here is that the deserialised json is not correctly getting mapped to a an object. Try to create a wrapper class over your model (Valores) and then try to map.
public class Valores
{
[JsonProperty("nome")]
public string Nome { get; set; }
[JsonProperty("valor")]
public double Valor { get; set; }
[JsonProperty("ultima_consulta")]
public int UltimaConsulta { get; set; }
[JsonProperty("fonte")]
public string Fonte { get; set; }
}
public class ValoresList
{
public boolean status { get; set; }
public Valores USD { get; set; }
public Valores EUR { get; set; }
public Valores ARS { get; set; }
public Valores GBP { get; set; }
public Valores BTC { get; set; }
}
And then map the wrapper class to the deserialised json.
public static async Task<ValoresList> GetAsync()
{
ValoresList valores = null;
using (var client = new HttpClient())
{
var json = await client.GetStringAsync("http://api.promasters.net.br/cotacao/v1/valores");
valores = JsonConvert.DeserializeObject<ValoresList>(json);
}
return valores;
}
The problem is the json returned contains a collection of Valores in a dictionary, you're trying to map the response to a single Valore object.
Your container wants to look like this. The key for the dictionary is the string representation of the currency.
class Container
{
public bool Status { get; set; }
public Dictionary<string, ValorInfo> Valores { get; set; }
}
Your Valor class is good as is, I renamed it to prevent a conflict on the class name to Valor property.
class ValorInfo
{
[JsonProperty("nome")]
public string Nome { get; set; }
[JsonProperty("valor")]
public double Valor { get; set; }
[JsonProperty("ultima_consulta")]
public int UltimaConsulta { get; set; }
[JsonProperty("fonte")]
public string Fonte { get; set; }
}
Finally this is how you use it, props to #dbc for spotting the user-agent requirement, that had me stumped!
async void Main()
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Accept", "application/json");
client.DefaultRequestHeaders.Add("User-Agent", "linqpad");
var response = await client.GetAsync("http://api.promasters.net.br/cotacao/v1/valores");
response.EnsureSuccessStatusCode();
var container = await response.Content.ReadAsAsync<Container>();
// do stuff with container...
}
}

How to Form the Service Request if i have list<Class>

Request Class Structure:
public class QueryParams {
public List<QueryParam> QueryParam { get; set; }
}
public class QueryParam {
public string Parameter { get; set; }
}
Service is Expecting in below format:
<typ:queryParams>
<typ:queryParam>
<typ:parameter>BUSINESS_CATEGORY</typ:parameter>
</typ:queryParam>
<typ:queryParam>
<typ:parameter>CATEGORY</typ:parameter>
</typ:queryParam>
</typ:queryParams>
How i can form the request?
using QueryParams = System.Collections.Generic.List<QueryParam>;
public class QueryParam {
public string Parameter { get; set; }
public QueryParam(string para) {
Parameter = para;
}
}
public class Program
{
public static void Main()
{
var Qp = new QueryParams() {
new QueryParam("BUSINESS_CATEGORY"),
new QueryParam("CATEGORY")
};
string QpXml = ToXml(Qp);
// Use your XML from here on
}
private static string ToXml(QueryParams Qp) {
StringBuilder Sb = new StringBuilder();
Sb.AppendLine("<typ:queryParams>");
foreach (var q in Qp) {
Sb.AppendLine("<typ:queryParam>");
Sb.AppendLine("<typ:parameter>" + q.Parameter + "</typ:parameter>");
Sb.AppendLine("</typ:queryParam>");
}
Sb.AppendLine("</typ:queryParams>");
return Sb.ToString();
}
}
See this .NET Fiddle

Parsing JSON into Object

Trying to get the result from a webservice call to return a Model. I eep getting the error:
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'CI.Models.Schedule' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
public Schedule getCourseSchedule()
{
var obj = new
{
States = new[] { new { State = "MX" } },
Zip = "",
Miles = "",
PaginationStart = 1,
PaginationLimit = 3
};
using (var client = new WebClient())
{
client.Headers[HttpRequestHeader.ContentType] = "apoplication/json";
var url = "http://192.168.1.198:15014/ShoppingCart2/CourseSchedule";
var json = JsonConvert.SerializeObject(obj);
byte[] data = Encoding.UTF8.GetBytes(json);
byte[] result = client.UploadData(url, data);
string returnjson = Encoding.UTF8.GetString(result);
Schedule sched = JsonConvert.DeserializeObject<Schedule>(returnjson);
return sched;
}
}
Schedule Model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Globalization;
namespace CI.Models
{
public class Schedule
{
public IEnumerable<Course> Courses { get; set; }
}
public class Course
{
/*
JSON Data returned from web service:
{
"ProgramGroup":"MR",
"ProgramCode":"RM",
"EventCode":"20160901MXMR",
"FormalDate":"September 1-2, 2016",
"StartDate":"2016\/09\/01",
"Price":5,
"LocName":"WB Hotel",
"LocAddress":"Av. Speedy Gonzales 220",
"LocCity":"Monterrey",
"LocState":"MX",
"LocZipCode":null,
"LicenseeURL":null,
"AgendaURL":"NA",
"SeatsAreAvailable":"2",
"GeneralInfoHTML":"General Info goes here.",
"GateKeeperHTML":null,
"EventType":"SS",
"TotalCourses":3
}
*/
public string ProgramGroup { get; set; }
public string ProgramCode { get; set; }
public string EventCode { get; set; }
public string FormalDate { get { return FormalDate; } set { FormalDate = convertFormalDateToSpanish(value); } }
public string StartDate { get; set; }
public double Price { get; set; }
public string LocName { get; set; }
public string LocAddress { get; set; }
public string LocCity { get ; set; }
public string LocState { get; set; }
public string LocZipCode { get; set; }
public string LicenseeURL { get; set; }
public string AgendaURL { get { return AgendaURL; } set { AgendaURL = buildAgendaLink(value); } }
public string SeatsAreAvailable { get; set; }
public string GeneralInfoHTML { get; set; }
public string GateKeeperHTML { get; set; }
public string EventType { get; set; }
public int TotalCourses { get; set; }
public string convertFormalDateToSpanish(string val)
{
DateTime TheDate = DateTime.Parse(StartDate);
string[] FormalDate = val.Split(" ".ToCharArray());
CultureInfo ci = new CultureInfo("es-ES");
string _Date = FormalDate[1].Replace("-", " al ").Replace(",", "");
string _Month = ci.TextInfo.ToTitleCase(TheDate.ToString("MMMM", ci));
val = string.Concat(_Date, " ", _Month);
return val;
}
private string buildAgendaLink(string val)
{
if (val.Trim() != "")
{
val = string.Concat("Agenda");
}
else
{
val = "Agenda";
}
return val;
}
}
}
Your server returns an array. Just try
Course[] courses = JsonConvert.DeserializeObject<Course[]>(returnjson);
Note that this is not an answer to your original problem, but I added it like an answer in order to explain my comment above with some actual code.
First problem with your code is that FormalDate and AgendaUrl properties simply won't work. Accessing them will result in a StackOverflowException, because you basically defined them recursively.
A property is merely syntax sugar for two separate getter/setter methods, so by writing this:
public class Course
{
public string FormalDate
{
get { return FormalDate; }
}
}
You are basically writing this:
public class Course
{
public string GetFormalDate()
{
// recursive call, with no terminating condition,
// will infinitely call itself until there is no
// more stack to store context data (and CLR
// will then throw an exception)
return GetFormalDate();
}
}
To fix that, you need to add an actual backing field, e.g.:
public class Course
{
private string _formalDate; // <-- this is a backing field;
// and this property uses the backing field to read/store data
public string FormalDate
{
get { return _formalDate; }
set { _formalDate = convertFormalDateToSpanish(value); }
}
}
Additionally, it's unusual for a property getter to return a different value than the one set through a setter. In other words, I would never expect this from a class:
var course = new Course();
course.StartDate = "2016/09/01";
course.FormalDate = "September 1-2, 2016";
Console.WriteLine(course.FormalDate); // prints "1 al 2 Septiembre" ?
I would rather move this functionality into a different class, or at least create different properties which return these values:
public class CourseInfo
{
// this is now a "dumb" auto-implemented property
// (no need for a backing field anymore)
public string FormalDate { get; set; }
// this read-only property returns the converted value
public string LocalizedFormalDate
{
get
{
return convertFormalDateToSpanish(FormalDate);
}
}
}

Categories