Azure Mobile Services Custom API Getting Bad Request on Client - azure

So I'm using azure mobile services backend to try and make a custom API. However I can't seem to connect to even the template table from the client. When you make a new Azure Mobile Service using the template they provide you with this values API controller that resembles this format
[MobileAppController]
public class ValuesController : ApiController
{
// GET api/values
[Route("api/values")]
public string Get()
{
return "test";
}
}
From the client I'm trying to invoke this endpoint like this
var result = mobileService.InvokeApiAsync<string>("values", HttpMethod.Get, null).Result;
And for some reason I keep getting this exception
{"The request could not be completed. (Bad Request)"}
{Method: GET, RequestUri: 'http://localhost:58457/api/values', Version: 1.1, Content: <null>, Headers:
{
X-ZUMO-FEATURES: AT
X-ZUMO-INSTALLATION-ID: b04f4e19-4f41-46ed-9767-9c1352037559
Accept: application/json
User-Agent: ZUMO/1.3
User-Agent: (lang=Managed; os=Windows; os_version=6.1.65536.7601; arch=Win32NT; version=1.3.30324.0)
X-ZUMO-VERSION: ZUMO/1.3 (lang=Managed; os=Windows; os_version=6.1.65536.7601; arch=Win32NT; version=1.3.30324.0)
}}
This is only the template too, so I need this to work before I get any of my custom endpoints up and running. Any ideas on what the issue may be?

You can opt out of version checking by setting a value of true for the app setting MS_SkipVersionCheck. Specify this either in your web.config or in the Application Settings section of the Azure Portal.
ms_skipversioncheck to true in the portal.

You say Mobile Service, but the controller you're using is MobileAppController.
This indicates you're actually using Mobile App. If you look in your server project packages.config, you may see something like this.
<package id="Microsoft.Azure.Mobile.Server" version="1.0.119.0" targetFramework="net45" />
I suspect that the 400 you are getting is because you're using a Mobile Client version less than 2.0.0.
In your client project package config, try using a newer client version, such as:
<package id="Microsoft.Azure.Mobile.Client" version="2.0.1" targetFramework="win81" />
You should also inspect the body of the 400 response to get an explicit error message. I expect it to say something like:
{"message":"No API version was specified in the request, this request needs to specify a ZUMO-API-VERSION of '2.0.0'. For more information and supported clients see: http://go.microsoft.com/fwlink/?LinkId=690568#2.0.0"}

I have gone through the below link
https://learn.microsoft.com/en-us/azure/app-service-mobile/app-service-mobile-client-and-server-versioning
which actually says both Mobile Apps client and server SDKs are originally based on those in Mobile Services, but they are not compatible with each other. That is, you must use a Mobile Apps client SDK with a Mobile Apps server SDK and similarly for Mobile Services. This contract is enforced through a special header value used by the client and server SDKs, ZUMO-API-VERSION.
So, you must add Headers in the request
HEADERS: ZUMO-API-VERSION: 2.0.0
Or
http://localhost/api/values/get?ZUMO-API-VERSION=2.0.0
Or
You can opt out of version checking by setting a value of true for the app setting MS_SkipVersionCheck, specify this in your web.config under

Actually even if you specify what version of client you are using in your package.config you will still get the same error of Bad Request. No Zumo version specified. You must pass into your InvokeApiAsync method a parameter specifying the version. For example:
var arguments = new Dictionary<string, string>
{
{"ZUMO-API-VERSION", "2.0.0" }
};
var result = MobileService.InvokeApiAsync<string>("CONTROLLERSNAME", "HttpMethod.Get", arguements).Result;
and bingo it will work.

Related

No 'Access-Control-Allow-Origin' header is present on the requested resource

Getting this error:
Access to fetch at 'https://myurl.azurewebsites.net/Player/1' from origin 'http://localhost:19006' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
I'm not the first with this error, but I feel like I have tried everything that one can find through searching for the problem. I'm developing a web API with ASP.net core, that's supposed to communicate with my react-native frontend. Problem is, I cannot for the life of me get the connection to work.
In program.cs I have added
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
builder.Services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
policy =>
{
policy.AllowAnyMethod();
policy.AllowAnyHeader();
policy.AllowAnyOrigin();
});
});
and
app.UseCors(MyAllowSpecificOrigins);
I have tried adding no cors to the method itself
[DisableCors]
[HttpGet("{id}")]
public List<Player> GetPlayers(int id)
{
return (from c in _context.Player.Take(1)
where c.PlayerId == id
select c).ToList();
}
I even deployed the server and database on Azure (I was supposed to sooner or later anyway) just hoping that would allow me to get it to work. The API runs fine if I visit the URL and run it through that one. It also works great if I host it locally and go through the web.
On Azure I've changed my cors settings to allow everything:
I can even access the API through expo web if I run it locally at the same time. But I need to be able to do it through my phone as well, or at least an android emulator. Neither of those works for neither a locally hosted server, or one that's on Azure.
How can I solve this?
Actually, shortly after setting my Azure cors settings, it did indeed start to work. Finally, I can at least demo it. Unfortunately, I still have no solution that solves it when hosting locally.

RestTemplate API call between microservice is Not working

I have 2 microservices based on SAP SDK 3.0 archetype binded by the same xsuaa service.From the first microservice A, I wanted to call the second microservice B by using rest template. It fails to call, as it is not able to authenticate. Can you find my approach is right?
Sharing the code below along with the error screenshot
Error:
<200,document.cookie="fragmentAfterLogin="+encodeURIComponent(location.hash)+";path=/";document.cookie="locationAfterLogin="+encodeURIComponent(location.href.split('#')[0].split(location.host)1)+";path=/";document.cookie="signature=pim93tQhbcWCYYAiFxYkwrHBY%2Fs%3D;path=/";location="https://xxxxx.hana.ondemand.com/oauth/authorize?response_type=code&client_id=sb-Ledify!t7251&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2Flogin%2Fcallback",{x-request-id=[k8h8rf33], x-frame-options=[SAMEORIGIN], Cache-Control=[no-cache, no-store, must-revalidate], Content-Type=[text/html], Content-Security-Policy=[script-src 'self' 'unsafe-inline'], Date=[Wed, 01 Apr 2020 11:23:01 GMT], Connection=[keep-alive], Content-Length=[620]}>
Note : localhost:5000 is my local approuter port and it is configured to call the second microservice which I have tested it in browser
Updated:
I have updated with getToken() but I am getting the below error in my local approuter.
Error Response:
xsapp.json Route
{
"source": "/notif-mock/(.*)",
"authenticationType": "xsuaa",
"destination": "notif-mock",
"csrfProtection": true
}
FYI, I have used the local approuter setup as per this post Link here
In the following line, you are concatenating a String with DecodedJWT:
String encodedAuth = "Bearer " + getJWTTokenDetails();
But DecodedJWT does not implement a toString() method. You must use getToken() instead.
Hint: For easier support handling please copy/paste your code, because text in screenshot cannot efficiently be referenced.
Arun,
Thanks for providing all the additional details. I recommend updating to SDK Version 3.16.1 and testing if it solves your issue.
I do it because version 3.9.0 which you're using at the moment has an incomplete implementation of security scenarios invoked by XSUAA.
We fixed many issues related to the handling of XSUAA and JWT validation in release 3.15.1. Please, check release notes for details..
If even after update your issue persists, we'll have to see how we can reproduce it or get more logs data from you as a response only doesn't provide enough clue on where it fails.
Hope it helps!

How to update Google Cloud Platform Legacy GAE and GCF Metadata Server endpoints

I am using firebase cloud functions with Node to send push notifications triggered by realtime database events.
I got this email from Google telling me to update my requests to use the v1 endpoint. The email states:
Our records show that you own projects with App Engine applications or Cloud Functions that are still calling the pre-GA v0.1 and v1beta1 endpoints of the App Engine and Cloud Functions metadata server.
Identify the projects, apps and functions which are making these requests.
Attached to this message you will find the list of projects, applications and functions that you own that have made requests to the v0.1 and v1beta1 metadata server endpoints between Sept 26, 2019 and Nov 1, 2019.
Comment: I know what project it is.
Upgrade your Google client libraries to the latest versions. See supported library versions for the list of Google SDKs that require an update.
Comment: this I don't understand. Do I need to do this?
If you are making direct requests to the legacy Metadata Server endpoints:
To ensure minimal interruption to your instances, please update your requests to the v1 endpoint before April 30, 2020.
Comment: I don't know if I'm making direct requests
How to upgrade from v1beta1 request to v1 requests:
If you are making direct requests to the v1beta1 URI, please follow the following steps to upgrade to the v1 URI:
Change the request URI to use v1 instead of v1beta1
Add this header to your request: “Metadata-Flavor: Google”
For example, if you’re currently making this request:
curl "http://metadata.google.internal/computeMetadata/v1beta1/instance/id"
Upgrade to v1 as follows:
curl "http://metadata.google.internal/computeMetadata/v1/instance/id” -H "Metadata-Flavor: Google"
How to upgrade from v0.1 requests to v1 requests:
If you are making direct requests to the v0.1 URI, please follow the following steps to upgrade to the v1 URI:
Change the request URI to use v1 instead of v0.1
Add this header to your request: “Metadata-Flavor: Google”
Use these instructions to map the v0.1 properties to the v1 properties
For example, if you’re currently making this request:
curl "http://metadata.google.internal/0.1/meta-data/instance-id"
Upgrade to v1 as follows:
curl "http://metadata.google.internal/computeMetadata/v1/instance/id” -H "Metadata-Flavor: Google"
Redeploy your application
The steps above will require another application deployment to take effect.
I searched the Google Cloud support webb (as suggested in the email) and here on SO. But I don’t understand how to do this.
Please bare in mind I’m a complete novice. Any help or advice is greatly appreciated!
UPDATE
Apparently this function has made requests to the v0.1 and v1beta1 metadata server endpoints:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendErrorInputWasSentPush = functions.database.ref('/errorInputs/{barcode}/{date}').onWrite((change, context) => {
const barcode = context.params.barcode
const dataAfter = change.after.val()
const input = dataAfter.input
const pushIDs = [
"",
""]
console.log(`Error input submitted.`)
const payload = {
notification: {
title: '',
body: '',
sound: "default"
}
};
const options = {
priority: "high",
timeToLive: 60 * 60 * 24
};
return admin.messaging().sendToDevice(pushIDs, payload, options);
});
Firebase versions:
"firebase-admin": "^8.0.0",
"firebase-functions": "^3.2.0"
If you never perform any query to http://metadata.google.internal/... URL from your code or script, that changes nothing!
If you use this URL, paste your code, we could help you.
UPDATE
Thanks to your details, I found the problem in the file src/auth/credential.ts of firebase-admin-node github project. Up to the version 8.1.0 the value of the line 32 is:
const GOOGLE_METADATA_SERVICE_PATH = '/computeMetadata/v1beta1/instance/service-accounts/default/token';
Use the version 8.2.0 or above to solve this

Azure Notification Hub registration from Javascript using REST services fails

I'm trying to get a registration on the Azure Notification Hub working from html/javascript code running in a web view host (Phonegap / Intel XDK). There is no client library available, so I try to use the REST API (documentation: ).
I have the following Javascript code:
function registerWithAzureNotificationHub()
{
var sas = "Endpoint=sb://eventpusher-ns.servicebus.windows.net/;SharedAccessKeyName=DefaultListenSharedAccessSignature;SharedAccessKey=69XuYoluyBKl6JkkN03Z1oNC7cFSZ4Ku0ZWmPuWoJzs=";
var data = '<?xml version="1.0" encoding="utf-8"?>\
<entry xmlns="http://www.w3.org/2005/Atom">\
<content type="application/xml">\
<MpnsRegistrationDescription xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/netservices/2010/10/servicebus/connect">\
<Tags>myTag, myOtherTag</Tags>\
<ChannelUri>https://eventpusher-ns.servicebus.windows.net/eventpusher</ChannelUri>\
</MpnsRegistrationDescription>\
</content>\
</entry>';
if (AppMobi.iswp8) {
window.alert("IS WP8");
}
else
{
window.alert("IS NOT WP8");
}
$.ajax({
type:"POST",
url: "https://eventpusher-ns.servicebus.windows.net/EVENTPUSHER/registrations/?api-version=2013-08",
contentType: "application/atom+xml;type=entry;charset=utf-8",
headers: {
"Authorization": sas,
"x-ms-version": "2013-08"
},
dataType: "xml",
data: data,
success: function(d) { window.alert("SUCCESS!"); },
error: function(msg) { window.alert("FAILURE:" + JSON.stringify(msg)); }
});
window.alert("SENT!");
}
In the above case I use the Intel XDK with the code running on a WP8 device, so I register for MPNS (Microsoft Push Notification Service).
The above code fails, and returns without descriptive information about the cause of the error.
Questions:
Is it possible to register a mobile device for Azure Notification Hub from javascript code using REST services?
What could be wrong with the above code? Is the ChannelUri the correct Uri?
It is definitely possible top use the REST interface from javascript.
In your code there are two main problems:
in the ChannelURI you should put the channelURI retrieved from the WindowsPhone HttpPushNotificationChannel (as in this tutorial).
the authorization header is a token that is created for your specific request. As described here
A sample using WinJS is available. We will work on having a PhoneGap specific sample very soon!
I did post a server side snippet to register the device with token to the hub and to be able to send out the notification here :
How to register devices to Azure Notification Hub from server side(with NodeJS sdk) ?
I also have the client side code using ngCordova and PushPlugin in Ionic, let me know if anyone wants to see it.

Sending a GET request to the path given in the route

I am trying to call a REST service from a URL like this:
example.org/account/someusername
I have defined request and response DTOs.
[Route("/account/{UserName}", "GET")]
public class AccountRequest : IReturn<AccountResponse>
{
public string UserName { get; set; }
}
public class AccountResponse
{
public int Id { get; set; }
public string UserName { get; set; }
public string Bio { get; set; }
}
Calling the service:
JsonServiceClient client = new JsonServiceClient("http://example.org");
AccountRequest request = new AccountRequest { UserName = "me" };
AccountResponse response = client.Get(request);
However when I call the Get on the client, it doesn't respect the route. When I check the client instance in debugger, AsyncOneWayBaseUri value is example.org/json/asynconeway/. This part is irrelevant because it doesn't mean request is sent to this URL. I actually have no idea where it sends the request. I don't get any errors and all of my properties in response object is null.
What am I missing here?
Consume 3rd Party REST / HTTP Apis
ServiceStack's Service Clients are opinionated to call ServiceStack web services as they have support for ServiceStack's pre-defined routes, built-in Auth, auto-route generation, built-in Error Handling, etc.
To call 3rd Party REST / HTTP Apis you can use the HTTP Utils that come with ServiceStack.Text, which provide succinct, readable pleasant API's for common data access patterns around .NET's HttpWebRequest, e.g:
List<GithubRepo> repos = "https://api.github.com/users/{0}/repos".Fmt(user)
.GetJsonFromUrl()
.FromJson<List<GithubRepo>>();
Consuming ServiceStack services with C# .NET Service Clients
I'm not seeing the reported behavior, are you using the latest version of ServiceStack on the client?
One way to test the generated url that gets used (without making a service call) is to call the TRequest.ToUrl(method) extension method (that the Service Clients uss) directly, e.g.
AccountRequest request = new AccountRequest { UserName = "me" };
request.ToUrl("GET").Print(); // /account/me
The same auto-generated route was used when I tried calling it via the JsonServiceClient, e.g:
var client = new JsonServiceClient("http://example.org");
var response = client.Get(request); //calls http://example.org/account/me
Route URL used in ServiceStack's Service Clients
ServiceStack will attempt to use the most appropriate route that matches the values populated in the DTO and HTTP Method you're calling with, if there is no matching route it will fallback to the pre-defined routes.
By default the original predefined routes will be used:
/api/[xml|json|html|jsv|csv]/[syncreply|asynconeway]/[servicename]
But ServiceStack now also supports the shorter aliases of /reply and /oneway, e.g:
/api/[xml|json|html|jsv|csv]/[reply|oneway]/[servicename]
Which you can opt-in to use in the clients by setting the flag:
client.UseNewPredefinedRoutes = true;
it doesn't respect the route
Are you getting a 404 or a Handler not found exception?
Make sure whatever assembly your 'AccountService' class is in is added to the 'assembliesWithServices' parameter when configuring your AppHost. It sounds like the your Route is not being picked up by ServiceStack.
public MyAppHost() : base("my app", typeof(AccountService).Assembly) { }
What does your Service class look like?
Something like below should work (don't forget the Service interface)
public class AccountService : Service
{
public object Any(AccountRequest request)
{
return new AccountResponse() { UserName = request.UserName};
}
}
Servicestack supports a number of different data formats, such as JSON, XML, JSV, CSV, etc. and supports a number of different endpoints for accessing this data out of the box. Please find below details of the supported endpoints that has been taken from the formats section of the SS documentation.
The clients provided by ServiceStack use the default endpoint, not the restful endpoint to access the data. The data is still accessible restfully, you can test this by navigating to the restful URL in your browser.
Restful Endpoints
You can define which format should be used by adding ?format={format} to the end of the URL.
?format=json
?format=xml
?format=jsv
?format=csv
?format=htm
Example: http://www.servicestack.net/ServiceStack.Hello/servicestack/hello/World!?format=json
Alternatively ServiceStack also recognizes which format should be used with the Accept http header:
Accept: application/json
Accept: application/xml
As you can see, this approach only works with json and xml.
Default endpoint
/servicestack/[xml|json|html|jsv|csv]/[syncreply|asynconeway]/[servicename]
Examples:
/servicestack/xml/[syncreply|asynconeway]/[servicename] will be XML
/servicestack/json/[syncreply|asynconeway]/[servicename] will be JSON
SOAP endpoint
The SOAP endpoint only supports XML of course.
UPDATE
The ServiceStack clients cannot be used to connect to a non-ServiceStack web service because they rely on behavior which is specific to ServiceStack. Its probably best to use something like RestSharp or one of the many other available clients that allow you to interact with a restful web service.
Thanks everyone for their answers. C# client was sending the request to the right address from the start, I debugged it with Fiddler. Only I wasn't deserializing it properly.
Account object was in the data property of the response, not the response itself. The client is good at working with REST services even if they are not built with ServiceStack. It is pretty cool.

Resources