Is there ability of translation of Json values on Azure Cognitive Services. I'm wondering the implementation on .Net core - azure-cognitive-services

I want to translate my Json values from one language to other languages but through the Azure Cognitive Services I can't rich my expectations.
Simple Text and Html based text were translating through Azure translator but Json values I don't know how implement it.

Check the azure cognitive services in azure portal. Create cognitive services using valid subscription and resource group with valid storage policy and public access.
Input of JSON:
{
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
Output:
{
"Consolidaciones": [
{
"authLevel": "anónimo",
"type": "httpTrigger",
"direction": "in",
"nombre": "req",
"métodos": [
"obtener",
"post"
]
},
{
"tipo": "http",
"dirección": "fuera",
"nombre": "res"
}
]
}
View Request:
[{
"text": "{
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}"
}]
View Response:
[{
"detectedLanguage": {
"language": "en",
"score": "1"
}}
"translations": [{
"text": "{
"Consolidaciones": [
{
"authLevel": "anónimo",
"type": "httpTrigger",
"direction": "in",
"nombre": "req",
"métodos": [
"obtener",
"post"
]
},
{
"tipo": "http",
"dirección": "fuera",
"nombre": "res"
}
]
}",
"to": "es"
}]
}]
Create Source and Destination containers in the storage account. In the form of folders and upload JSON file to be translated into the source code and get all the keys mentioned above and modify in the below code block.
Code Block in C#
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.Text;
class Program
{
static readonly string route = "/batches";
private static readonly string endpoint = "https://<NAME-OF-YOUR-RESOURCE>.cognitiveservices.azure.com/translator/text/batch/v1.0";
private static readonly string key = "<YOUR-KEY>";
static readonly string json = ("{\"inputs\": [{\"source\": {\"sourceUrl\": \"https://YOUR-SOURCE-URL-WITH-READ-LIST-ACCESS-SAS\",\"storageSource\": \"AzureBlob\",\"language\": \"en\"}, \"targets\": [{\"targetUrl\": \"https://YOUR-TARGET-URL-WITH-WRITE-LIST-ACCESS-SAS\",\"storageSource\": \"AzureBlob\",\"category\": \"general\",\"language\": \"es\"}]}]}");
static async Task Main(string[] args)
{
using HttpClient client = new HttpClient();
using HttpRequestMessage request = new HttpRequestMessage();
{
StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
request.Method = HttpMethod.Post;
request.RequestUri = new Uri(endpoint + route);
request.Headers.Add("Ocp-Apim-Subscription-Key", key);
request.Content = content;
HttpResponseMessage response = await client.SendAsync(request);
string result = response.Content.ReadAsStringAsync().Result;
if (response.IsSuccessStatusCode)
{
Console.WriteLine($"Status code: {response.StatusCode}");
Console.WriteLine();
Console.WriteLine($"Response Headers:");
Console.WriteLine(response.Headers);
}
else
Console.Write("Error");
}
}
}

Related

Ocelot Swagger MMLib.SwaggerForOcelot showing "No operations defined in spec!"

I am using Ocelot gateway and for swagger document using "MMLib.SwaggerForOcelot" library.
For some swagger Key, swagger UI is showing "No operations defined in spec!" and swagger JSON is coming without paths like
{
"openapi": "3.0.1",
"info": {
"title": "Admin API",
"version": "v1"
},
"paths": {},
"components": {
"schemas": {}
}
}
Ocelot Configuration Route is
{
"DownstreamPathTemplate": "/api/admin/v{version}/{everything} ",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5000
}
],
"UpstreamPathTemplate": "/api/admin/v{version}/{everything}",
"UpstreamHttpMethod": [],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 1000,
"TimeoutValue": 900000
},
"SwaggerKey": "AdminAPI"
}
and Swagger Configuration is
"SwaggerEndPoints": [
{
"Key": "AdminAPI",
"Config": [
{
"Name": "Admin API",
"Version": "v1",
"Url": "http://localhost:5000/swagger/v1/swagger.json"
}
]
}
]
after reviewing the MMLib.SwaggerForOcelot source code, it looks like something to do with the version in the downstream path, any clue on how this can be fixed?
The issue is that MMLib.SwaggerForOcelot is not considering {version} while doing Ocelot transformation.
RouteOptions has a property TransformByOcelotConfig which is set to true by default, so once swagger JSON is obtained from downstream, the transformation will be done.
here, it will try to find the route from the route configuration like below and if not found it will delete the route from swagger JSON
private static RouteOptions FindRoute(IEnumerable<RouteOptions> routes, string downstreamPath, string basePath)
{
string downstreamPathWithBasePath = PathHelper.BuildPath(basePath, downstreamPath);
return routes.FirstOrDefault(p
=> p.CanCatchAll
? downstreamPathWithBasePath.StartsWith(p.DownstreamPathWithSlash, StringComparison.CurrentCultureIgnoreCase)
: p.DownstreamPathWithSlash.Equals(downstreamPathWithBasePath, StringComparison.CurrentCultureIgnoreCase));
}
The problem is StartsWith will return false since swagger JSON path will be like
/api/admin/v{version}/Connections
and route config is like
/api/admin/v{version}/{everything}
and version will replace with the version given in swagger options so that it will become
/api/admin/v1/{everything}
Fix to this problem will be
Either set "TransformByOcelotConfig":false in swagger option
"SwaggerEndPoints": [
{
"Key": "AdminAPI",
"TransformByOcelotConfig":false,
"Config": [
{
"Name": "Admin API",
"Version": "v1",
"Url": "http://localhost:5000/swagger/v1/swagger.json"
}
]
}
]
Or Change the route, just to have {everything} keyword
{
"DownstreamPathTemplate": "/api/admin/{everything} ",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5000
}
],
"UpstreamPathTemplate": "/api/admin/{everything}",
"UpstreamHttpMethod": [],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 1000,
"TimeoutValue": 900000
},
"SwaggerKey": "AdminAPI"
}

Pact provider verification fails with : For input string: "\null"

I am trying to validate on the provider side but getting error -
Verifying a pact between DataConsumer and DataProvider
[Using File pact/DataConsumer-DataProvider.json]
Given some state
a request for json data
Request Failed - For input string: "\null"
Not sure what did I miss here.
My Pojo -
#EqualsAndHashCode
#RequiredArgsConstructor
#Builder(toBuilder = true)
#JsonDeserialize(builder = DataModel.DataModelBuilder.class)
public class DataModel {
#JsonProperty("name")
private final String name;
#JsonProperty("price")
private final double price;
}
Pact -
{
"provider": {
"name": "DataProvider"
},
"consumer": {
"name": "DataConsumer"
},
"interactions": [
{
"description": "a request for json data",
"request": {
"method": "GET",
"path": "/get/ice/2.0"
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json; charset\u003dUTF-8"
},
"body": {
"price": 10,
"name": "some name"
},
"matchingRules": {
"header": {
"Content-Type": {
"matchers": [
{
"match": "regex",
"regex": "application/json(;\\s?charset\u003d[\\w\\-]+)?"
}
],
"combine": "AND"
}
}
},
"generators": {
"body": {
"$.name": {
"type": "ProviderState",
"expression": "\\${name}",
"dataType": "STRING"
},
"$.price": {
"type": "ProviderState",
"expression": "\\${price}",
"dataType": "FLOAT"
}
}
}
},
"providerStates": [
{
"name": "some state"
}
]
}
],
"metadata": {
"pactSpecification": {
"version": "3.0.0"
},
"pact-jvm": {
"version": "3.6.15"
}
}
}
Test -
#ExtendWith(SpringExtension.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#Provider("DataProvider")
#PactFolder(value = "pact")
public class ContractVerificationTest {
#TestTemplate
#ExtendWith(PactVerificationSpringProvider.class)
void pactVerificationTestTemplate(PactVerificationContext context) {
context.verifyInteraction();
}
#State("some state")
void testPact() {
}
}
Code -
https://github.com/nrworld4/pact-consumer-demo
https://github.com/nrworld4/pact-demo-provider
You aren't returning the values (name, price) from your provider state annotation in your provider test (it's currently doing nothing) so when Pact tries to replace the values dynamically in the request they are null.
Do you actually need them to be generated by the provider in the first place?
See
https://pactflow.io/blog/injecting-values-from-provider-states/ for a detailed example of how to use and fix.
Update
Could it be that you're double escaping the parameters?
In the example:
.queryParameterFromProviderState("accountNumber", "\${accountNumber}", "100")
In your code:
.valueFromProviderState("price", "\\${price}", 10.0)

PACT jvm matching rules are being ignored when running test

I'm using PACT JVM https://github.com/DiUS/pact-jvm/tree/master/provider/pact-jvm-provider-junit
I don't know why the matching rules in my contact are being ignored.
My HTTP test
#RunWith(SpringRestPactRunner.class) // Say JUnit to run tests with custom Runner
#Provider("provDataTest")// Set up name of tested provider
#PactBroker(host="pact-broker.services", port = "80")
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT,
properties = {"spring.profiles.active=dev"},
classes = Application.class)
public class ContractTesting {
private static String token;
#BeforeClass //Method will be run once: before whole contract test suite
public static void setUpService() {
//Run DB, create schema
//Run service
//...
System.out.println("Now service in default state");
}
#TargetRequestFilter
public void exampleRequestFilter(HttpRequest request) {
}
#State("Check correct data json structure in case code: 401")
public void checkDataInCaseUnauthorized() {
}
#TestTarget // Annotation denotes Target that will be used for tests
public final Target target = new HttpTarget(8082);
And my Contract file
{
"provider": {
"name": "provDataTest"
},
"consumer": {
"name": "test"
},
"interactions": [
{
"description": "Read all links_401",
"request": {
"method": "GET",
"path": "/v1/consumer/me/link_social_account",
"headers": {
"invalidAuth": "401"
}
},
"response": {
"status": 401,
"headers": {
"Content-Type": "text/json;charset=utf-8"
},
"body": {
"error": {
"code": 401,
"message": "session incorrect",
"errors": []
}
},
"matchingRules": {
"body": {
"$.error": {
"matchers": [
{
"match": "type"
}
],
"combine": "AND"
},
"$.error.code": {
"matchers": [
{
"match": "integer"
}
],
"combine": "AND"
},
"$.error.message": {
"matchers": [
{
"match": "type"
}
],
"combine": "AND"
},
"$.error.errors[*].message": {
"matchers": [
{
"match": "type"
}
],
"combine": "AND"
},
"$.error.errors[*].field": {
"matchers": [
{
"match": "type"
}
],
"combine": "AND"
}
},
"header": {
"Content-Type": {
"matchers": [
{
"match": "text/json;charset=utf-8",
"regex": "regex"
}
],
"combine": "AND"
}
}
}
},
"providerStates": [
{
"name": "Check correct data json structure in case code: 401"
}
]
}
],
"metadata": {
"pactSpecification": {
"version": "3.0.0"
},
"pact-jvm": {
"version": "3.2.11"
}
}
}
And show error after run
Read all links_401 returns a response which has a matching body
Read all links_401 returns a response which has a matching
body=BodyComparisonResult(mismatches={/=[BodyMismatch(expected=[B#480e8a7a, actual=[B#10378c35, mismatch=Actual body '[B#10378c35' is not equal to the expected body '[B#480e8a7a', path=/, diff=null)]},
diff=[-{"error":{"code":401,"message":"session incorrect","errors":[]}},
+{"error":{"code":401,"message":"session incorrect, please login again (CR_A1004)","errors":[]}}])
I have tried to change regex but the problem is still happening.
It is only correct when message data correct.
Please help to give my point incorrect.
Thanks,
The problem is with your content-type header: "Content-Type": "text/json;charset=utf-8". The proper content type for JSON payloads should be application/json. That is why the matchers are not being applied, because the body is being treated as a text payload. Just change the content type and then the body will be parsed as a JSON document and the matchers will be applied to the fields.

ServiceStack: OpenApi import in Azure Api Management Gateway

We are running a Dotnet Core 2.2 service using ServiceStack 5.7, and need to throttle it. So we want to put it behind a Azure Api Management Gateway (apim) - it runs in a Azure App Service.
We have enabled OpenApi feature using
self.Plugins.Add(new OpenApiFeature());
When we export our OpenApi definition we get the following:
"paths": {
...
"/api/search": {
"post": {
"tags": [
"api"
],
"operationId": "SearchRequestsearch_Post",
"consumes": [
"application/x-www-form-urlencoded"
],
"produces": [
"application/json"
],
"parameters": [
{
"name": "Filters",
"in": "formData",
"type": "array",
"items": {
"$ref": "#/definitions/FilterDto"
},
"collectionFormat": "multi",
"required": false
}
],
"responses": {
"200": {
"description": "Success",
"schema": {
"$ref": "#/definitions/SearchResponse"
}
}
},
"deprecated": false,
"security": [
{
"Bearer": []
}
]
},
"parameters": [
{
"$ref": "#/parameters/Accept"
}
]
}
}
...
"definitions": {
"FilterDto": {
"title": "FilterDto",
"properties": {
"Field": {
"description": "The field to filter on",
"type": "string",
"enum": [
"None",
"DestinationName",
"DocumentId"
]
},
"Values": {
type": "array",
"items": {
"type": "string"
}
},
"Type": {
"type": "string",
"enum": [
"Equals",
"NotEquals",
"RangeNumeric",
"RangeDate"
]
}
},
"description": "FilterDto",
"type": "object"
}
...
}
The problem is that it is not supported to have a parameter with an array of a type (defined in #/definitions/FilterDto). And it fails with:
Parsing error(s): JSON is valid against no schemas from 'oneOf'. Path 'paths['/api/search'].post.parameters[1]', line 1, position 666.
Parsing error(s): The input OpenAPI file is not valid for the OpenAPI specificate https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md (schema https://github.com/OAI/OpenAPI-Specification/blob/master/schemas/v2.0/schema.json).
In the Azure portal.
In c# (ServiceStack) we have defined the following:
public class SearchRequest : SearchRequestBase, IReturn<SearchResponse>
{
public SearchRequest()
{
Filters = new List<FilterDto>();
}
[ApiMember(Name = "Filters"]
public List<FilterDto> Filters { get; set; }
}
public class FilterDto
{
[ApiMember(Name = "Field"]
[ApiAllowableValues("Field", typeof(FilterAndFacetField))]
public FilterAndFacetField Field { get; set; }
[ApiMember(Name = "Values")]
public List<string> Values { get; set; }
[ApiMember(Name = "Type")]
[ApiAllowableValues("Type", typeof(FilterType))]
public FilterType Type { get; set; }
public FilterDto()
{
Values = new List<string>();
}
}
Have anyone successfully managed to import a OpenApi using array of $ref in the parameters from ServiceStack into a Api Management?

API Platform filter entity data

I just start to use Api platform and immediately stuck with problem how to filter data.
I have entity User and i want to filter data that are present in response ( JSON API format)
{
"links": {
"self": "/api/users"
},
"meta": {
"totalItems": 2,
"itemsPerPage": 30,
"currentPage": 1
},
"data": [
{
"id": "/api/users/1",
"type": "User",
"attributes": {
"_id": 1,
"username": "jonhdoe",
"isActive": true,
"address": null
}
},
{
"id": "/api/users/3",
"type": "User",
"attributes": {
"_id": 3,
"username": "test",
"isActive": true,
"address": null
}
}
]
}
so I want to remove e.g. User with id 3, but not use filters sent via request. I just want to set filter that will be always run when someone go to /api/users.
I look to api-platform extensions but this will be applied on each request e.g. /api/trucks. So at end I just want to get something like
{
"links": {
"self": "/api/users"
},
"meta": {
"totalItems": 1,
"itemsPerPage": 30,
"currentPage": 1
},
"data": [
{
"id": "/api/users/1",
"type": "User",
"attributes": {
"_id": 1,
"username": "jonhdoe",
"isActive": true,
"address": null
}
}
]
}
As you pointed out, extensions are the way to go.
The applyToCollection method gets a $resourceClass parameter containing the current resource class.
So you can apply the WHERE clause only for a specific class in this method like:
public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null)
{
if (User::class === $resourceClass) {
$queryBuilder->doSomething();
}
// Do nothing for other classes
}

Resources