Azure Custom Vision Api POST Request error, even correct ID's - c#

I'm trying to publish my Custom Vision Iteration after I trained it. But I always get a "Bad Request" Error.
I'm trying with the following line of code:
trainingApi.PublishIteration(ProjectID, iteration.Id, "Model", predictionResourceId);
It should Publish my Iteration but I just get an error.
I re-checked all my ID's but everything looks fine. Has the model name be something specific (start with lower letter or something)?
Edit:
I tried it now with a POST Request in Postman but now I receive:
{
"code": "BadRequestInvalidPublishTarget",
"message": "Invalid prediction resource id"
}
But I re-checked my Prediction Resource ID and it's correct.
Edit 2:
I thin I put the wrong thing into predictionId in the POST request, I just put in a ID but I think it should have been the /subscriptions/... part like described by microsoft. The problem now is:
{
"code": "BadRequestInvalidPublishTarget",
"message": "Invalid prediction id, please pass a prediction resource id."
}
For me this means it doesn't receive a prediction resource id, but I'm lost so I'm out of ideas what the problem could be.
Edit 3:
I forgot to add my POST Request:
https://xxx.cognitiveservices.azure.com/customvision/v3.0/training/projects/xxx/
iterations/xxx/publish?publishName=Model&predictionId=/subscriptions/xxx/
resourceGroups/CustomVision/providers/Microsoft.CognitiveServices/accounts/xxx

Publish using POST request
If you want to ensure that you have the right syntax, you can check using Custom vision portal by doing the same steps.
For example when I try to publish an iteration of a project, I can see the following call in the console:
https://westeurope.api.cognitive.microsoft.com/customvision/v3.3/Training/projects/ID_OF_MY_PROJECT/iterations/ID_OF_MY_ITERATION/publish?predictionId=%2Fsubscriptions%2FID_OF_MY_AZURE_SUBSCRIPTION%2FresourceGroups%2FNAME_OF_MY_RESOURCE_GROUP%2Fproviders%2FMicrosoft.CognitiveServices%2Faccounts%2FNAME_OF_MY_CUSTOM_VISION_PREDICTION_RESOURCE&publishName=NAME_OF_MY_ITERATION
Demo:
So yes, the "publicationId" value is looking like the one you mentioned but you have to encode the value of this string.
So change this:
predictionId=/subscriptions/xxx/
resourceGroups/CustomVision/providers/Microsoft.CognitiveServices/accounts/xxx
to
predictionId=%2Fsubscriptions%2Fxxx%2F
resourceGroups%2FCustomVision%2Fproviders%2FMicrosoft.CognitiveServices%2Faccounts%2Fxxx
in your call.
And be careful to use a prediction resource, not a training one.
Publish using C#
Here is a demo using C# and the official Custom Vision package hosted on Nuget (here)
using System;
using Microsoft.Azure.CognitiveServices.Vision.CustomVision.Training;
namespace so65714960
{
class Program
{
private static CustomVisionTrainingClient _trainingClient;
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
_trainingClient = new CustomVisionTrainingClient(new ApiKeyServiceClientCredentials("PUT_YOUR_TRAINING_KEY_HERE"));
// I'm specifying my endpoint here as I'm working on West Europe region
_trainingClient.Endpoint = "https://westeurope.api.cognitive.microsoft.com/";
var projectId = new Guid("4b...a5"); // Put your Project Id here
var iterationId = new Guid("9d...e"); // Put your iteration Id here
// Get iteration information
var targetIteration = _trainingClient.GetIteration(projectId, iterationId);
Console.WriteLine($"Iteration publish resource Id: '{targetIteration.OriginalPublishResourceId}'");
// If originalPublishResourceId is not null, it is already published
// For this demo purpose, we unpublish first to publish again after if it is already published
if (!string.IsNullOrWhiteSpace(targetIteration.OriginalPublishResourceId))
{
_trainingClient.UnpublishIteration(projectId, iterationId);
// Force status refresh
targetIteration = _trainingClient.GetIteration(projectId, iterationId);
Console.WriteLine($"Iteration publish resource Id after unpublish: '{targetIteration.OriginalPublishResourceId}'");
}
// Publish
var publicationResourceId = "/subscriptions/7c...e8/resourceGroups/Cognitive_Demo/providers/Microsoft.CognitiveServices/accounts/NRO-Cognitive-CustomVision-WestEurope-Prediction-S0";
var publication = _trainingClient.PublishIteration(projectId, iterationId, "Publication1", publicationResourceId);
// Force status refresh
targetIteration = _trainingClient.GetIteration(projectId, iterationId);
Console.WriteLine($"Iteration publish resource Id after publish: '{targetIteration.OriginalPublishResourceId}'");
}
}
}
See my Azure resource used:

Related

Microsoft.Azure.CognitiveServices.Language.SpellCheck NuGet not working with Bing Search API (unauthorized)

I'm using .net-core3.1 with Microsoft.Azure.CognitiveServices.Language.SpellCheck NuGet package. I've read through entire documentation around Bing/cognitive API but I still find it very confusing as there are multiple APIs doing the same thing.
I got the API key from Microsoft.BingSearch on portal.azure.com and I'm using the free subscription. My subscription should however be valid as I am already using their LUIS without problems. Azure links to https://learn.microsoft.com/en-us/bing/search-apis/bing-spell-check/quickstarts/rest/python for quick start but this does not work for me ("https://api.bing.microsoft.com/v7.0/SpellCheck" url gives me "NotFound" using the code below with my key).
code sample:
var x = new SpellCheckClient(new ApiKeyServiceClientCredentials("<API_KEY>"));
// endpoints I tried:
// x.Endpoint = "https://westeurope.api.bing.microsoft.com/v7.0/spellcheck";
// x.Endpoint = "https://cognitiveservices.azure.com/bing/v7.0";
// x.Endpoint = "https://api.bing.microsoft.com"; -- Not found
// x.Endpoint = "https://cognitiveservices.azure.com"; -- The requested name is valid, but no data of the requested type was found.
var y = await x.SpellCheckerWithHttpMessagesAsync("gona");
Using default endpoint gives me Unauthorized error code.
Anyone has any idea on how to use this API?
You are right, the endpoint seems to be wrong. As you can see in the documentation here, regarding this value:
Supported Cognitive Services endpoints (protocol and hostname, for
example: "https://westus.api.cognitive.microsoft.com",
"https://api.cognitive.microsoft.com").
So if you are using West Europe, it should be "https://westus.api.cognitive.microsoft.com"
You can also check your API key by directly testing the console here: https://westeurope.dev.cognitive.microsoft.com/docs/services/5f7d486e04d2430193e1ca8f760cd7ed/operations/57855119bca1df1c647bc358
Choose your resource region (the one selected during key creation on Azure portal)
Set your key value in "Ocp-Apim-Subscription-Key" field
Edit the "text" value in the query parameters
Run the request

Apple Pay web using c# (testing on ngrok)

I am trying to test my Apple pay application using ngrok. However, the merchant validation fails and I don't get the required token. The Apple pay button is visible on the iPhone that, I am using for testing.
I have used this link to create a sample application: https://github.com/justeat/ApplePayJSSample
I have got the following (as instructed in the above URL)
The pfx file (placed in the project path)
The merchant validation txt file (placed in .wellknown folder)
The domain is verified in the apple pay website
Can some one suggest how to test the application? Or the possible reason why the merchant validation is failing?
What should be the requestUri (is it different for test and Prod?) and can the display name be any thing or is it certificate specific?
JsonDocument merchantSession;
if (!ModelState.IsValid ||
string.IsNullOrWhiteSpace(model?.ValidationUrl) ||
!Uri.TryCreate(model.ValidationUrl, UriKind.Absolute, out Uri requestUri))
{
return BadRequest();
}
// Create the JSON payload to POST to the Apple Pay merchant validation URL.
var request = new MerchantSessionRequest()
{
DisplayName = _options.StoreName,
Initiative = "web",
InitiativeContext = Request.GetTypedHeaders().Host.Value,
MerchantIdentifier = _ApplePayServieBusiness.GetMerchantIdentifier(),
};
merchantSession = await _ApplePayServieBusiness.GetMerchantSessionAsync(requestUri, request, cancellationToken);
UPDATE:
I have put my steps that I used for MerchantValidation in the below link. However, I am still not able to hit onpaymentauthorized function in site.js
https://github.com/justeat/ApplePayJSSample/issues/68#issuecomment-795687727

Azure Custom Vision API returning different results than project portal?

I've create a custom vision project to recognise characters (A, B, C...).
What is interesting: if I upload an image of a character (in this case an "N") to the vision API portal it will tell me that it is 99.9% sure it is an "N":
If however I use the client libraries to predict the very same image, I'm getting 53% that it is a "W" and only 37% that it is an "N":
I double checked that the latest iteration is the published one
I double checked that I'm using the correct project ID
My endpoint is set to "https://westeurope.api.cognitive.microsoft.com" in the CustomVisionPredictionClient
The code to get the prediction on my client:
var client = new CustomVisionPredictionClient()
{
ApiKey = predictionKey,
Endpoint = endpoint
};
var result = await client.PredictImageAsync(Guid.Parse(projectId), imageStream).ConfigureAwait(false);
var prediction = result.Predictions.FirstOrDefault();
Where does this difference come from and how to fix because according to the tests I did by uploading images the results are close to 100% correct no matter which character image I upload?
UPDATE: I noticed that there was an update for the client libraries. They went from 0.12pre to 1.0stable. After the update the PredictImageAsync is gone and replaced with DetectImageAsync. This expected as an additional parameter a model name. I tried using the name of the iteration and after a while the method returns with an internal server error. So not sure what to try next.
The comment above pointed my into the right direction - thanks!
The new client library has got two methods ClassifyImage and DetectImage (and various variations of them) which replace the previously used ones including PredictImage which I was using with the preview version of the client library.
To classify an image (which is what I wanted to do) ClassifyImage should of course be used. The new code looks like this and delivers an almost 100% correct prediction:
var client = new CustomVisionPredictionClient()
{
ApiKey = predictionKey,
Endpoint = endpoint
};
var result = await client.ClassifyImageAsync(Guid.Parse(projectId), "Iteration12", imageStream).ConfigureAwait(false);
var prediction = result.Predictions.FirstOrDefault();
endpoint is the URL of the region the vision API is hosted in, in my case https://westeurope.api.cognitive.microsoft.com.
predictionKey is available on the CustomVision.AI site in your project, so is the projectId
The publishedName parameter is the name of the iteration to use (in my case "Iteration12"

Receiving custom WebHooks in a Windows Form Application

I am working to make an internal application available from an external location. To accomplish this I’m looking into different options like the use of a rest API or using a socket server which can be placed between the old application and the database on the server. One of the concerns of the end product is that if multiple users alter the same data and sent this to the server that there is the possibility that they overwrite each other’s changes. The planned approach for this is have a server sided log for data changes, and notify the user that relevant data has been altered to give them the choice to reload their form. The latter part is the issue from which my question has come forth. Unlike sockets web protocols do not work bidirectional. Potential fixes that I have found are polling, framing and WebHook of which the latter seem to be the most efficient.
However looking at the different available WebHook receiver samples they seem to have something in common. They use either MVC or WebAPI and all have an altered WebConfig in which the method config.InitializeCustomWebHooks(); has been added.
I’ve been trying to find a way to add this in by altering the Program.cs without success.
Also I’ve tried to find a method that has to do with Hooks using the HttpClient (which I’ve used for the rest of my demo application so far), WebClient and HttpResponse. However this search also did not bear any fruits. Also the only post of someone who tried to accomplish something similar (have a windows forms application listen to GitHub) that I found got a [response][1] that made me believe that webhooks and windows forms just don’t go together.
This search has ended with me wondering or:
Is it a possibility to consume an API 2 services WebHooks with a windows form application?
And if possible I would like to be informed how to do this?
For now my API 2 server has been pretty much altered according the example provided by [Asp.Net][2]
And my client has implemented the CustomWebHookHandler from the CustomReceiver from the same.
Edit for next issue:
note: both client and server contain the same packages as used in the repo as shown by Peter Bons.
The client contains a secret key within the app.config, matching the key within the subscribe method and the new Startup.cs has been called (I am able to sent echo's to the client sided hosted server) so that part is working. The registration class also matches up with the example repo
Client initiates the webhook with the following method:
public void SubscribeTo(String subscribeString)
{
HttpResponseMessage result;
// Create a webhook registration
Registration registration = new Registration
{
WebHookUri = $"{adressReceiver}/api/webhooks/incoming/custom",
Description = "A message is posted.",
Secret = "12345678901234567890123456789012",
Filters = new List<string> { "EmployeeChanged" }
};
result = client.PostAsJsonAsync(#"webhooks/registrations", registration).Result;
string resultString = result.ToString();
}
Where adress receiver is the same string that was used to start the echoable webservice.
Upon debugging the method the following actions server/client occur:
on the line containing result = the server sided debug point in CustomFilterProvider.GetFiltersAsync get's triggered.
At the return method it shows that 1 filer was returned with the Name: "EmployeeChanged" back on the client the resultString contains the StatusCode: Created
During the method the client has the system output:
ClientApp.exe Information: 0 : Registered 'IWebHookReceiver' instances with the following names: custom.
ClientApp.exe Information: 0 : Processing incoming WebHook request with receiver 'custom' and id ''.
ClientApp.exe Information: 0 : Registered configuration setting 'Custom' for ID '''.
And the server:
Application Insights Telemetry (unconfigured):
{
"name": "Microsoft.ApplicationInsights.Dev.RemoteDependency",
"time": "2017-09-12T10:16:25.8947601Z",
"tags": {
"ai.internal.nodeName": "PC-78.vericon.nl",
"ai.operation.id": "1348c1c9-4b7a5ac6dd5f1940",
"ai.cloud.roleInstance": "PC-78.vericon.nl",
"ai.internal.sdkVersion": "rdddsd:2.4.1-1362"
},
"data": {
"baseType": "RemoteDependencyData",
"baseData": {
"ver": 2,
"name": "GET /api/webhooks/incoming/custom",
"id": "|1348c1c9-4b7a5ac6dd5f1940.",
"data":
"http://localhost:55999/api/webhooks/incoming/custom?echo=e9f7b03ca8aa4226a7a9dfc99dacff16",
"duration": "00:00:00.2046329",
"resultCode": "200",
"success": true,
"type": "Http",
"target": "localhost:55999",
"properties": { "DeveloperMode": "true" }
}
}
}
Application Insights Telemetry (unconfigured):
{
"name": "Microsoft.ApplicationInsights.Dev.Request",
"time": "2017-09-12T10:14:50.0204275Z",
"tags": {
"ai.internal.nodeName": "PC-78.vericon.nl",
"ai.operation.name": "POST /api/webhooks/registrations",
"ai.operation.id": "lXKbEdh4GOU=",
"ai.location.ip": "::1",
"ai.cloud.roleInstance": "PC-78.vericon.nl",
"ai.internal.sdkVersion": "web:2.4.1-1362"
},
"data": {
"baseType": "RequestData",
"baseData": {
"ver": 2,
"id": "|lXKbEdh4GOU=.1348c1c8_",
"name": "POST /api/webhooks/registrations",
"duration": "00:01:36.1228603",
"success": true,
"responseCode": "201",
"url": "http://localhost:55997/api/webhooks/registrations",
"properties": { "DeveloperMode": "true" }
}
}
}
After a bit of research my reasoning for this output is that the server sends an echo request to the ip given by the client to see or it is a reachable destination. The code created also implies that the server found this adress because otherwise a code BadRequest would occur
So I think that the webhook get's correctly established futher on in the application I have got a method that makes a post request to the server. I put a debug point in the server sided method to see what happens (there's also is a debug point in my client handler).
after doing the client sided action that should get me in my controller the debug point within indeed get's triggered in my method:
public async Task<IHttpActionResult> Post(Employee e)
{
await this.NotifyAsync(CustomFilterProvider.EmployeeChanged, new { Employee = e });
if (EmployeeModifier.updateEmployee(e))
{
log.Info("User: " + User.Identity.Name + " Updated an employee with the following new value " + Newtonsoft.Json.JsonConvert.SerializeObject(e));
return Ok();
}
else
{
log.Error("User: " + User.Identity.Name + " failed to update an employee");
return BadRequest();
}
}
when stepping through it it follows the route towards to return Ok()
the client receives the system output:
ClientApp.exe Information: 0 : Processing incoming WebHook request with receiver 'custom' and id ''.
However the debug point within the clients handler never get's triggered.
the handler for now looks like:
class CustomWebHookHandler : WebHookHandler
{
public CustomWebHookHandler()
{
}
public override Task ExecuteAsync(string generator, WebHookHandlerContext context)
{
System.Windows.Forms.MessageBox.Show("In handler");
return Task.FromResult(true);
}
}
My client startup.cs Configuration method looks like:
public void Configuration(IAppBuilder appBuilder)
{
var config = new HttpConfiguration();
var controllerType = typeof(WebHookReceiversController);
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
"DefaultApi",
"api/{controller}/{id}",
new { id = RouteParameter.Optional }
);
config.InitializeReceiveCustomWebHooks();
var traceWriter = config.EnableSystemDiagnosticsTracing();
traceWriter.IsVerbose = true;
traceWriter.MinimumLevel = TraceLevel.Error;
appBuilder.UseWebApi(config);
}
So that contains the var controllerType
I hope this is enough relevant code for you, my fear is that my server is only sending echo's/ping requests to my client.
But I don't know how to change that since I've tried both NotifyAsync and NotifyAllAsync, with and without Filter( in client Registration class instance). The clients OWIN hosts keeps up for sure since it is echo able and the client output shows that it actually does receive a message from the server but that's where I'm crashed.

Azure Notification Hub installation not updating tags

I am attempting to update the tags of an installation within Azure Notification Hub after registration. I am following several guides for this, notably here and here.
Both of these guides suggest that the following code should work however it is plainly not; the tag never gets updated. There are no errors, and I can guarantee that the installationId is correct. I am guessing I am setting the path/value of the tag incorrectly.
// in constructor:
var _notificationHub = NotificationHubClient.CreateClientFromConnectionString(Settings.ConnectionStrings.NotificationHub, Settings.Defaults.NotificationHubName);
// in WebApi endpoint:
var installationUpdates = new List<PartialUpdateOperation>();
var userDetail = _userDetailRepo.Get(id);
installationUpdates.Add(new PartialUpdateOperation
{
Operation = UpdateOperationType.Replace,
Path = "/tags/interestedin", // is this incorrect?
Value = interestedIn.ToUpper()
});
userDetail.InterestedIn = interestedIn;
await Task.WhenAll(
_userDetailRepo.InsertOrReplace(userDetail),
_notificationHub.PatchInstallationAsync(installationId, installationUpdates));
Here is the installation object's tags, as per VS:
I also tried hardcoding the path to Path = "/tags/interestedin:W" but it made no difference.
Can someone tell me if I am doing something wrong here, and if so how I should amend my code. Thanks.
Unfortunately, Path = "/tags/interestedin" is not going to work as of now. We are currently working on wildcards' support. Once it is done, something like "/tags/interestedin*" will work fine for you.
While Path = "/tags/interestedin:W" should be OK. If you could provide namespace name, hub name, and a timeframe, then I'll take a look at logs to check what is going on there.

Categories