Azure: is it possible to create rest service without virtual machine? - azure

Is there any opportunity to create a custom REST service without creating a virtual machine (no matter, some other server with software to work directly with azure SQL) to serve that.
Situation:
I have an azure SQL instance
There is a bunch of stored procedures in few SQL databases that i want to call as a REST service
I want to call this procedures as a REST service, sending them a parameters (string, int) and get a result in JSON format. Also I'm interested in access control for such kind of service.
I can create all that stuff using my own software (connecting to Azure SQL), but is there such opportunity in azure itself?
I don't need full solution, I need an answer if is it possible and what kind of solutions(resources) on azure should I use. I've already read a lot, but I still can't find a solution.
rem: I need Azure because of using it's storage and analytics engines in project.

Azure WebApp or Azure Functions would be the way to go for you, they offer the ability to run code without having to manage the underlying structure. Depending on your scenario you might settle with one or the other.

I believe the easiest way is using Azure Functions with Http Trigger template. The only thing you'll need to do is extract the variables from content or querystring:
using System.Net;
using System.Threading.Tasks;
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
log.Info($"C# HTTP trigger function processed a request. RequestUri={req.RequestUri}");
// parse query parameter
string name = req.GetQueryNameValuePairs()
.FirstOrDefault(q => string.Compare(q.Key, "name", true) == 0)
.Value;
// Get request body
dynamic data = await req.Content.ReadAsAsync<object>();
// Set name to query string or body data
name = name ?? data?.name;
return name == null
? req.CreateResponse(HttpStatusCode.BadRequest, "Please pass a name on the query string or in the request body")
: req.CreateResponse(HttpStatusCode.OK, "Hello " + name);
}
more info: https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook

I would definitely recommend Azure functions for this. In the previous answers you can see how to generate response, and here is example how to call stored procedure - https://www.codeproject.com/Articles/1169531/Sending-events-from-Azure-Event-Hub-to-Azure-SQL-D
Azure SQL has FOR JSON clause that can transform results of sql query to JSON text so you can directly stream it as a Http response.

Related

Check if a file exists in azure blob container

I have an azure blob container name "x" and I want to check if a file name "a.jpg" exists in that blob or not and return true or false based on that. It seems easy but there isn't a clear answer when I google it.
It is clearly mentioned in the document, if you are using c# you can use ExistsAsync method
public async Task<bool> FileExists(string fileName)
{
return await directory.GetBlockBlobReference(fileName).ExistsAsync();
}
You can also use REST Api if you want.
https://learn.microsoft.com/en-us/rest/api/storageservices/get-blob-metadata
A lot more trouble... but works too.
Request The Get Blob Metadata request may be constructed as follows.
HTTPS is recommended. Replace myaccount with the name of your storage
account:
TABLE 1 GET or HEAD Method Request URI HTTP Version
https://myaccount.blob.core.windows.net/mycontainer/myblob?comp=metadata
https://myaccount.blob.core.windows.net/mycontainer/myblob?comp=metadata&snapshot=

Azure Event Grid - Resource Write Success - Filter by email address

Azure Event Grid is used to capture all Azure Resource Write Success activities. I'm trying to filter users by email address.
data.clamins.name gives the username in similar way when tried data.claims.'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name' the filter is not working as expected.
Should there be escape characters to make 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name' filter work ?
This is used for below use case of tagging newly created resources for deletion
Event grid invoke azure automation script when there is a Resource Write Success event in Azure
Script tag resources with expire tag
A second script take care of deletion.
I think, there is no either documented or undocumented way/workaround using this kind of naming in the advanced filtering. It will be nice to have it for claims, for instance:
data.claims.schemas_ws200505identity_emailaddress
where the schemas_ws200505identity_ represents value of http://schemas.xmlsoap.org/ws/2005/05/identity/claims/
Anyway, for your solution the place for filtering this property is in the subscription handler. The following code snippet shows this example:
public static async Task Run(JObject eventGridEvent, ILogger log)
{
// ...
var emailaddress = eventGridEvent["data"]?["claims"]?["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"]?.Value<string>();
log.LogInformation($"emailaddress = {emailaddress}");
// ...
await Task.CompletedTask;
}

Azure Function as a Web API performance and pricing

We are planning to build a web application, and I was hoping someone could help us to decide whether to use Azure App Service or Azure Function for providing rest API to the client side.
Our requirements are as follows.
Authentication and authorization
CRUD on Azure SQL and Cosmos DB
Multi region
100,000,000 API calls per month
At first, we were going to build the backend using Azure App Service. But after studying pros and cons on Azure Functions, Azure Functions became more appealing to us.
So is it even a good idea to build a web application that depends on Azure Functions as a REST API provider?
Does anyone have an experience building, managing and scaling up and out Azure Functions as a REST API provider?
Is it even a good idea to build a web application that depends on Azure Functions as a REST API provider?
It seems you are planning to have REST API using Web Service or Azure Function. Your decision is perfect I would say. For Azure Function its not mandatory to have web service for that. Azure function would be best option for you. You can implement all the feature that Web API provides. So if your target is only develop API then you can start with Azure Function with no other alternative. Its outstanding actually!
Does anyone have an experience building, managing and scaling up and out Azure Functions as a REST API provider?
I am working with Azure Function for our AI Base Bot with LUIS integration. From my understanding it's a very easily maintainable, fastest response time, you can build it from anywhere. So you can undoubtedly go with Azure function.
Why Choose Azure Function:
It's stateless, need not any server to run
Full REST, can call from anywhere any Region
Can develop both Azure Portal and local Visual Studio
Cost-effective, you can pay only how much you use.
Multiple language support
Easy Authorization and Authentication functionality
No limit of calling as per your consumption plan
Do A Lot With Azure Function:
You can develop a robust API service with Azure functions. It has many outstanding features. Please check Check here
Authorization and Authentication:
You can simply integrate your authorization and authentication on your function App. Even you can implement it on each function separately or on a full application. It supports most of the popular authentication provider for example:
Azure Active Directory
Microsoft Identity
Goggle
Facebook
Twitter auth
See how can you implement authentication:
Step:1
Step:2
Rest Function Code Sample:
Here I am giving you a simple code snippet to start with: though it's on Azure Table Storage, but help you to develop azure function and CRUD concept.
Your Sample Class:
public class YourSampleClass
{
public string PartitionKey { get; set; }
public string RowKey { get; set; }
}
Table Storage Class:
public class TableStorageClass
{
public TableStorageClass()
{
}
public TableStorageClass(DynamicTableEntity entity)
{
PartitionKey = entity.PartitionKey;
RowKey = entity.RowKey;
}
public string PartitionKey { get; set; }
public string RowKey { get; set; }
}
Azure Function V2 Example:
public static class FunctionReadFromTableStorage
{
[FunctionName("FunctionReadFromTableStorage")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
//Read Request Body
var content = await new StreamReader(req.Body).ReadToEndAsync();
//Extract Request Body and Parse To Class
YourSampleClass objYourSampleClass = JsonConvert.DeserializeObject<YourSampleClass>(content);
// Validate param because PartitionKey and RowKey is required to read from Table storage In this case , so I am checking here.
dynamic validationMessage;
if (string.IsNullOrEmpty(objYourSampleClass.PartitionKey))
{
validationMessage = new OkObjectResult("PartitionKey is required!");
return (IActionResult)validationMessage;
}
if (string.IsNullOrEmpty(objYourSampleClass.RowKey))
{
validationMessage = new OkObjectResult("RowKey is required!");
return (IActionResult)validationMessage;
}
// Table Storage operation with credentials
var client = new CloudTableClient(new Uri("https://YourStorageURL.table.core.windows.net/"),
new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials("YourStorageName", "xtaguZokAWbfYG4QDkBjT+YourStorageKey+T/kId/Ng+cl3TfYHtg=="));
var table = client.GetTableReference("YourTableName");
//Query filter
var query = new TableQuery()
{
FilterString = string.Format("PartitionKey eq '{0}' and RowKey eq '{1}'", objYourSampleClass.PartitionKey, objYourSampleClass.RowKey)
};
//Request for storage query with query filter
var continuationToken = new TableContinuationToken();
var storageTableQueryResults = new List<TableStorageClass>();
foreach (var entity in table.ExecuteQuerySegmentedAsync(query, continuationToken).GetAwaiter().GetResult().Results)
{
var request = new TableStorageClass(entity);
storageTableQueryResults.Add(request);
}
//As we have to return IAction Type So converting to IAction Class Using OkObjectResult We Even Can Use OkResult
var result = new OkObjectResult(storageTableQueryResults);
return (IActionResult)result;
}
}
Point To Remember:
In case of Azure Portal execution just get rid of FunctionReadFromTableStorage class
You Need following reference to execute above code
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Microsoft.WindowsAzure.Storage.Table;
using System.Collections.Generic;
Postman Request Pattern:
Function Invoke Sample:
{
"PartitionKey": "Your Param According to Table Storage Design" ,
"RowKey": "Your Param According to Table Storage Design",
"Directory": "Your Param According to Table Storage Design"
}
See The Screen Shot:
Post Man Response:
Response is subject to my own table design
[
{
"partitionKey": "Microsoft SharePoint Server",
"rowKey": "2016"
}
]
See The Screen Shot Below:
Note: For CosmosDb Integration you could check here. Azure SQL with Function take a look here.

Adapting hypermedia links based on environment

I have an on-premise ASP.NET Web API that's querying on-premise data. The plan is for the client web application to call an Azure Function which will deal with authentication (Azure AD B2C) and validating the request before actually forwarding the request to the on-premise API itself (over a VPN).
The API is generating Hypermedia links that point to the API itself. This works nicely when querying the API directly as each of the links helps in the discovery of the application.
This API is currently in use locally within the organisation, but we now need to expose it so it can be consumed over the web. We don't want to expose the API directly, we'd rather route it through a Function App that can authenticate, validate and perform any other logic we may need.
The question I have is, how would you translate these URLs to an endpoint in the Azure Function? i.e., I would really like the consuming web application to be able to use these Hypermedia links directly, and have the Azure Function route them to the correct API endpoint.
In an ideal world, we'd have the links exposed on the client, which would map to the resource. As the API isn't exposed, how do we route it via the Function App?
It sounds like what you want is for Azure Functions to operate as a reverse proxy.
One trick to achieve this is to have one HttpTrigger that catches all traffic that hits your function application. You can do this by setting the properties route: "{*uri}" and methods: ["get", "post", "put", "patch", "delete"] in the function.json. You can add additional HTTP methods to the methods list as necessary. These should catch all requests in the form "https://{app-name}.azurefunctions.net/api/*".
The code below is a rough outline of how you could achieve the redirect from your function app to the unexposed API. In it's current representation, the relative URI path after /api/ will be redirected to your unexposed api with the exact same body request.
using System.Net;
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
//Validation logic here
string actualUrl = "{hosturl}/";
string proxyUrl = "https://{app-name}.azurewebsites.net/api/";
req.RequestUri = new Uri(req.RequestUri.ToString().Replace(proxyUrl, actualUrl));
req.Headers.Host = req.RequestUri.Host;
using(var client = new HttpClient())
{
return await client.SendAsync(req);
}
}
You can now generate all of your Hypermedia links pointing to your function hostname, and they will be properly redirected.
NOTE: If you expect many instances of the function to spin up (i.e. a high concurrent usage of your function), then it is possible that you will run into SocketException errors as documented here.

Azure .NET SDK - List all virtual machines, failed to authenticate

Using the new Windows Azure SDK for .NET, I want to get a list of all virtual machines.
Piecing together the early documentation, here's what I came up with:
// This is a custom cert I made locally. I uploaded it to Azure's Management Certificates and added it to my local computer's cert store, see screenshot below.
X509Certificate2 myCustomCert = await this.GetAzureCert();
var credentials = new CertificateCloudCredentials(mySubscriptionId, myCustomCert);
using (var cloudServiceClient = CloudContext.Clients.CreateCloudServiceManagementClient(credentials))
{
credentials.InitializeServiceClient(cloudServiceClient); // Is this required? The next call fails either way.
// This line fails with exception: "The server failed to authenticate the request. Verify that the certificate is valid and is associated with this subscription."
var services = await cloudServiceClient.CloudServices.ListAsync(CancellationToken.None);
}
My first thought was the cert was bad, but I am able to successfully call the Azure REST API using my custom certificate. As you can see below, it is properly added to the Azure Management Certificates and associated with my subscription:
What am I doing wrong?
Here's another option - rather than upload a cert, try pulling your management cert out of your publishsettings file and using the X509Certificate's constructor that takes a byte[]. Then, pass that parameter the result of a call to Convert.FromBase64String, passing it the string representation of your management certificate from your publishsettings file.
Also, take a look at the Compute management client rather than the Cloud Service Management client. There are more features specific to the compute stack in that client at this time. The code below is a demonstration of such an approach. Note, my _subscriptionId and _managementCert fields are both strings, and I just hard-code them to the values from my publishsettings file as I described above.
public async static void ListVms()
{
using (var client = new ComputeManagementClient(
new CertificateCloudCredentials(_subscriptionId,
new X509Certificate2(Convert.FromBase64String(_managementCert)))
))
{
var result = await client.HostedServices.ListAsync();
result.ToList().ForEach(x => Console.WriteLine(x.ServiceName));
}
}
There's a parameterless ListAsync method that's an extension method. Try importing the Microsoft.WindowsAzure.Management namespace (or the Microsoft.WindowsAzure.Management.Compute namespace). Once you see the parameterless ListAsync method you should be good. I'll also mock up some code to resemble what you're trying to accomplish and offer up a more comprehensive answer by the end of the day.

Resources