400 Bad request when posting json array to spring controller on azure - azure

I am getting 400 bad request when I am trying to pass a json array to spring controller on azure app service. However I am not getting any error when I try to run the service from my local environment. My request is as follows,
$http.post(appPath + '/app/temp/saveTempData?tempData=' + JSON.stringify(row.data)).success(function(result) {
if (result.result) {
toaster.pop("successful", "Updated successfully");
} else {
toaster.pop("warning", "Something went wrong please try again later.");
}
})
Where row.data is an json array.On the spring controller I have the following,
#RequestMapping(value = "/saveTempData", method = RequestMethod.POST)
#ResponseBody
public String saveTempData(#RequestParam JSONArray tempData) {
}
This code is working in my local machine, but on the azure app service it gives me 400 bad request. Thank you.

We have to encode the request parameter when sending json array to the app service controller using encodeURIComponent like follows,
$http.post(appPath + '/app/temp/saveTempData?tempData=' + encodeURIComponent(JSON.stringify(row.data))).success(function(result) {
if (result.result) {
toaster.pop("successful", "Updated successfully");
} else {
toaster.pop("warning", "Something went wrong please try again later.");
}
})

Related

Microsoft Bot Framework - Call from Azure app service to external Web API

I had a Microsoft Bot Framework project that connect to Web API(that not hosted in azure).
in local host everything was work fine. but when i was deployed the Bot to an Azure app service. it's seem that the call is failed(and the Bot not return any response).
this is my post request:
public static string Post(List<ActionInputParams> data, string url)
{
using (WebClient wc = new WebClient())
{
wc.Headers[HttpRequestHeader.ContentType] = "application/json;charset=utf-8";
try
{
var res = wc.UploadString(url, "POST", JsonConvert.SerializeObject(data));
return res;
}
catch (Exception ex)
{
return "error " + ex.Message;
}
}
}
my question: there is a problem to call to external Web API from Azure app service? or i just missing something?
in the "log stream" i getting a 500 error:
HTTP Error 500.0 - Internal Server Error
The page cannot be displayed because an internal server error has occurred.

Why a 400 response from Azure endpoint for Postman but works fine with the Alexa console?

I am new to developing Alexa skills so I am using a sample I found on the web as a C# endpoint hosted on Azure. It works correctly with the Alexa console but when I try to test the same endpoint with the Postman app, I get a 400 error.
When I use the Alexa console, it displays the JSON input that it sends to the endpoint and the JSON output that it receives from the endpoint. If I copy the JSON input and paste it into Postman and send it to the same endpoint, I get a 400 error. Obviously, I am missing something.
The following are my two source files and the JSON input.
RollTheDice.cs
public static class RollTheDice
{
[FunctionName("RollTheDice")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log)
{
log.Info("C# HTTP trigger function processed a request.");
var speechlet = new RollTheDiceSpeechlet();
return await speechlet.GetResponseAsync(req);
}
}
RollTheDiceSpeechlet.cs
public class RollTheDiceSpeechlet : SpeechletBase, ISpeechletWithContext
{
public SpeechletResponse OnIntent(IntentRequest intentRequest, Session session, Context context)
{
try
{
// Default to 6 sides if not specified
if (!int.TryParse(intentRequest.Intent.Slots["DiceType"].Value, out int numSides))
numSides = 6;
var rollResults = new Random().Next(Math.Max(1, numSides - 1)) + 1; // Account for random returning '0'
return new SpeechletResponse
{
ShouldEndSession = false,
OutputSpeech = new PlainTextOutputSpeech { Text = $"I rolled a {numSides} sided die and got a {rollResults}." }
};
}
catch (Exception ex)
{
return new SpeechletResponse
{
ShouldEndSession = false,
OutputSpeech = new PlainTextOutputSpeech { Text = ex.Message }
};
}
}
public SpeechletResponse OnLaunch(LaunchRequest launchRequest, Session session, Context context)
{
return new SpeechletResponse
{
ShouldEndSession = false,
OutputSpeech = new PlainTextOutputSpeech { Text = "Welcome to the Roll the Dice. Ask me to roll the dice." }
};
}
public void OnSessionEnded(SessionEndedRequest sessionEndedRequest, Session session, Context context)
{
return;
}
public void OnSessionStarted(SessionStartedRequest sessionStartedRequest, Session session, Context context)
{
return;
}
}
JSON Input
Again, everything works fine but when I test it with Postman I get a 404 error.
The endpoint is C# serverless function that I developed in Visual Studio 201.
When I run it locally, I copy/paste the URL in the Postman app and send a post. See attached screenshots.
As the error suggest you are missing Signature and SignatureCertChainUrl headers. These helps to protect your endpoint and verify that incoming requests were sent by Alexa. Any requests coming from other sources should be rejected. When you test it via Test Console these headers are included and you get successful response.
Headers:
Signature
SignatureCertChainUrl
There are two parts to validating incoming requests:
Check the request signature to verify the authenticity of the request.
Check the request timestamp to ensure that the request is not an old request.
More information on verifying that the request was sent by Alexa here

How can I catch exception from backend server using IMobileServiceSyncTable - InsertAsync?

I'm using IMobileServiceSyncTable from Azure Mobile App. In InsertAsync operation, on the backend server side, I had some validations for the data and, if that validations failure, I want throw Exception from the server side. I tried return InternalServerError(), throw HttpResponseException, but never worked on the client side. I debbuged the Post method in server side, the server throws the exception or return InternalServerError, but in the mobile client, don't occurs error.
Can anyone help me?
Here is my code on the client side:
public async Task<bool> AddPaciente(Paciente novoPaciente)
{
//other things
try
{
await _pacienteTable.InsertAsync(novoPaciente);
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
Debug.WriteLine(e.StackTrace);
throw new WebException(AppResources.MensagemFalhaConexaoServidorAzure);
}
await SyncPaciente();
return true;
}
Here is my post method on the backend server side
// POST tables/Paciente
public async Task<IHttpActionResult> PostPaciente(Paciente novoPaciente)
{
//other things
if (paciente != null)
{
var responseMessage = new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent("Já existe um paciente com esse token cadastrado.")
};
//throw new HttpResponseException(responseMessage);
return InternalServerError(new Exception("Já existe um paciente com esse token cadastrado."));
}
}
You should listen to the response status code.
var response = await _pacienteTable.InsertAsync(novoPaciente);
if (response.IsSuccessStatusCode) {
var content = await response.Content.ReadAsStringAsync ();
}
else
{
//Here handle the error code
throw new WebException(AppResources.MensagemFalhaConexaoServidorAzure);
}
I'm using IMobileServiceSyncTable from Azure Mobile App. In InsertAsync operation, on the backend server side, I had some validations for the data and, if that validations failure, I want throw Exception from the server side.
For IMobileServiceSyncTable, you are dealing with An Offline Client which means that IMobileServiceSyncTable<T>.InsertAsync would directly insert data into the local SQLite store on your mobile client-side. Until you manually call MobileServiceClient.SyncContext.PushAsync(), then your local data store would be pushed to your mobile backend. For this approach, I would recommend you make sure that you need to validate the inputs before you saving them into the local data store, otherwise your push operations would fail, then you need to force your client user to adjust the existing inputs even after it has been successfully added before.
If you use An Online Client as follows, then both your approaches for throwing the exception would be immediately returned to your client.
var mobileClient= new MobileServiceClient("https://{your-mobile-app-name}.azurewebsites.net");
var _pacienteTable= mobileClient.GetTable<Paciente>();
await _pacienteTable.InsertAsync(novoPaciente);
Moreover, I used the following code line for catching the exception:
try
{
await table.InsertAsync(item);
}
catch (MobileServiceInvalidOperationException ex)
{
//TODO:
//await ex.Response.Content.ReadAsStringAsync(); //get detailed response content
}
catch (Exception e)
{
//TODO: other uncaught exception
}
Also, for the similar issue, you could leverage Fiddler to capture the network traces to narrow down this issue, make sure your client-side could correctly receive the relevant response.

unable to call azure signalr hub method using azure signalr rest api

I have created a sample .net core app with azure signalr service and hosted at local iis.
i) I am using below url in postman to call hub method:
http://azuresignalr:5002/api/v1-preview/hub/:NotificationHub
ii) calling with postman with below body:
{
"Message": {
"target": "BroadcastMessage",
"arguments": [
"test method"
]
}
}
iii) My c# class :
public class NotificationHub:Hub
{
public string TestConnection()
{
return "connected";
}
[HttpPost]
public void BroadcastMessage([FromBody]object message)
{
message = "Modified Message from Azure Signal R server " + message;
Clients.All.SendAsync("broadcastMessage", message);
}
}
but I am getting 404 error in postman.
Any help or document regarding its implementation is highly appreciated.
You can't do that, because no connection is established. A hub is not the same like a controller which you can use for creating restendpoints.
Normally your client should create a connection to the server, after that you can communicate over this "channel".
Why do you do this?
(For details signalr information start with https://www.asp.net/signalr)

Azure App Service Error 405 - The request could not be completed. (Method Not Allowed)

I'm working with Azure App Service .NET backend with a Xamarin.iOS app. I am able to successfully register a new user and I can see the user's details in the database. I have a custom ApiController, which handles the registration and the I'm able to save the details with a successful POST call.
However, when I try to log into the app, I get the following error:
{Microsoft.WindowsAzure.MobileServices.MobileServiceInvalidOperationException: The request could not be completed. (Method Not Allowed)
Below is my code:
The RegistrationController in the backend which successfully makes a POST call
[MobileAppController]
[RoutePrefix("api/register")]
[AllowAnonymous]
public class RegisterController : ApiController
{
[HttpPost]
[Route("newuser")]
public HttpResponseMessage NewUser(RegistrationRequest request)
{
// Registration code in here
}
}
This is how I call this function on the client side:
public async Task<Result<UserProfile>> RegisterUser(RegistrationWrapper registrationrequest)
{
try
{
var registrationRequest = new JObject();
registrationRequest.Add("username", registrationrequest.username);
registrationRequest.Add("password", registrationrequest.password);
registrationRequest.Add("email", registrationrequest.email);
registrationRequest.Add("phone", registrationrequest.phone);
registrationRequest.Add("firstname", registrationrequest.firstname);
registrationRequest.Add("lastname", registrationrequest.lastname);
var result = await client.InvokeApiAsync("register/newuser", registrationRequest);
// Handle result here
}
catch (Exception ex)
{
return Result<UserProfile>.Failure(ex.Message + ex.StackTrace + ex.InnerException);
}
}
Custom AuthController which handles the login
This POST call fails with the error described above.
[MobileAppController]
[RoutePrefix("api/auth")]
public class AuthController : ApiController
{
public HttpResponseMessage Post(AuthenticationRequest credentials)
{
try
{
//Authentication code goes here
catch (Exception e)
{
Console.WriteLine("Ërror :" + e.Message);
Console.WriteLine(e.StackTrace);
return Request.CreateResponse(HttpStatusCode.InternalServerError, new
{
Stacktrace = e.StackTrace,
ErrorMessage = e.Message,
Credentials = credentials
});
}
}
How I invoke this function from the client side
async Task<Result<Account>> Login(string username, string password)
{
try
{
var credentials = new JObject();
credentials.Add("username", username);
credentials.Add("password", password);
var result = await client.InvokeApiAsync("auth", credentials);
//Handle result here
}
catch (Exception ex)
{
return Result<Account>.Failure(ex, ex.Message + ex.StackTrace);
}
}
}
I'm not sure why it's failing during the log in. Any ideas?
After trying tons of solutions found here on StackOverflow, the one that finally worked for me was this first answer found on a similar question.
It seems that the http POST call is redirected to https.
After enabling authentication on your App Service in the Azure portal, you need to change the url to https.
So I changed mine from this:
http//{my_site}.azurewebsites.net
To this:
https//{my_site}.azurewebsites.net
On the client side, and now used this new one to create my local sync tables.
Everything works as expected now.
The HTTP status code 405 is returned when an API endpoint is called with a wrong (Not Allowed) HTTP method. For example, if instead of a POST request the endpoint is called with a GET request.

Resources