Azure Search using REST c# - azure

I am trying to run the following code:
public class Item
{
[JsonProperty(PropertyName = "api-key")]
public string apikey { get; set; }
}
[[some method]]{
var url = "https://[search service name].search.windows.net/indexes/temp?api-version=2016-09-01";
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(HttpMethod.Put,url))
{
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var sItem = new Item { apikey = [AzureSearchAdminKey] };
var tststring = JsonConvert.SerializeObject(sItem);
var body=new StringContent(tststring, Encoding.UTF8,"application/json" );
request.Content = body;
request.Method = HttpMethod.Put;
using (HttpResponseMessage response = httpClient.SendAsync(request).Result)
{
var stringr = response.Content.ReadAsStringAsync().Result;
Console.WriteLine(stringr);
Console.ReadLine();
}
}
}
}
I get the following error:
"Error reading JObject from JsonReader. Path '', line 0, position 0."
Could someone from search team tell me what I did wrong?

The api key should be in the HTTP header, and the index definition should be in the HTTP body.
Here's some sample code for creating a data source, index, and indexer, which reads from an Azure SQL DB and indexes its rows.
class Program
{
static void Main(string[] args)
{
var searchServiceName = "[search service name]";
var apiKey = "[api key]";
var dataSourceName = "[data source name]";
var indexName = "[index name]";
var indexerName = "[indexer name]";
var azureSqlConnectionString = "[Azure SQL connection string]";
var azureSqlTableName = "[table name]";
using (var httpClient = new HttpClient())
{
var dataSourceDefinition = AzureSqlDatasourceDefinition(azureSqlConnectionString, azureSqlTableName);
var putDataSourceRequest = PutDataSourceRequest(searchServiceName, apiKey, dataSourceName, dataSourceDefinition);
Console.WriteLine($"Put data source {putDataSourceRequest.RequestUri}");
Console.WriteLine();
var putDataSourceResponse = httpClient.SendAsync(putDataSourceRequest).Result;
var putDataSourceResponseContent = putDataSourceResponse.Content.ReadAsStringAsync().Result;
Console.WriteLine(putDataSourceResponseContent);
Console.WriteLine();
var indexDefinition = IndexDefinition();
var putIndexRequest = PutIndexRequest(searchServiceName, apiKey, indexName, indexDefinition);
Console.WriteLine($"Put index {putIndexRequest.RequestUri}");
Console.WriteLine();
var putIndexResponse = httpClient.SendAsync(putIndexRequest).Result;
var putIndexResponseContent = putIndexResponse.Content.ReadAsStringAsync().Result;
Console.WriteLine(putIndexResponseContent);
Console.WriteLine();
var indexerDefinition = IndexerDefinition(dataSourceName, indexName);
var putIndexerRequest = PutIndexerRequest(searchServiceName, apiKey, indexerName, indexerDefinition);
Console.WriteLine($"Put indexer {putIndexerRequest.RequestUri}");
Console.WriteLine();
var putIndexerResponse = httpClient.SendAsync(putIndexerRequest).Result;
var putIndexerResponseContent = putIndexerResponse.Content.ReadAsStringAsync().Result;
Console.WriteLine(putIndexerResponseContent);
Console.WriteLine();
var runIndexerRequest = RunIndexerRequest(searchServiceName, apiKey, indexerName);
Console.WriteLine($"Run indexer {runIndexerRequest.RequestUri}");
Console.WriteLine();
var runIndexerResponse = httpClient.SendAsync(runIndexerRequest).Result;
Console.WriteLine($"Success: {runIndexerResponse.IsSuccessStatusCode}");
Console.ReadLine();
}
}
static HttpRequestMessage PutDataSourceRequest(string searchServiceName, string apiKey, string dataSourceName,
string datasourceDefinition)
{
var request = new HttpRequestMessage(HttpMethod.Put,
$"https://{searchServiceName}.search.windows.net/datasources/{dataSourceName}?api-version=2016-09-01");
request.Headers.Add("api-key", apiKey);
var body = new StringContent(datasourceDefinition, Encoding.UTF8, "application/json");
request.Content = body;
return request;
}
static HttpRequestMessage PutIndexRequest(string searchServiceName, string apiKey, string indexName,
string indexDefinition)
{
var request = new HttpRequestMessage(HttpMethod.Put,
$"https://{searchServiceName}.search.windows.net/indexes/{indexName}?api-version=2016-09-01");
request.Headers.Add("api-key", apiKey);
var body = new StringContent(indexDefinition, Encoding.UTF8, "application/json");
request.Content = body;
return request;
}
static HttpRequestMessage PutIndexerRequest(string searchServiceName, string apiKey, string indexerName,
string indexerDefinition)
{
var request = new HttpRequestMessage(HttpMethod.Put,
$"https://{searchServiceName}.search.windows.net/indexers/{indexerName}?api-version=2016-09-01");
request.Headers.Add("api-key", apiKey);
var body = new StringContent(indexerDefinition, Encoding.UTF8, "application/json");
request.Content = body;
return request;
}
static HttpRequestMessage RunIndexerRequest(string searchServiceName, string apiKey, string indexerName)
{
var request = new HttpRequestMessage(HttpMethod.Post,
$"https://{searchServiceName}.search.windows.net/indexers/{indexerName}/run?api-version=2016-09-01");
request.Headers.Add("api-key", apiKey);
return request;
}
static string AzureSqlDatasourceDefinition(string connectionString, string tableName)
{
return #"
{
""description"": ""azure sql datasource"",
""type"": ""azuresql"",
""credentials"": { ""connectionString"": """ + connectionString + #""" },
""container"": { ""name"": """ + tableName + #""" },
""dataChangeDetectionPolicy"": {
""#odata.type"": ""#Microsoft.Azure.Search.HighWaterMarkChangeDetectionPolicy"",
""highWaterMarkColumnName"": ""highwatermark""
},
""dataDeletionDetectionPolicy"": {
""#odata.type"": ""#Microsoft.Azure.Search.SoftDeleteColumnDeletionDetectionPolicy"",
""softDeleteColumnName"": ""deleted"",
""softDeleteMarkerValue"": ""true""
}
}
";
}
static string IndexDefinition()
{
return #"
{
""fields"": [
{
""name"": ""id"",
""type"": ""Edm.String"",
""key"": true,
""searchable"": true,
""sortable"": true,
""retrievable"": true
},
{
""name"": ""field1"",
""type"": ""Edm.String"",
""searchable"": true,
""retrievable"": true
},
{
""name"": ""field3"",
""type"": ""Edm.Int32"",
""retrievable"": true
}
]
}
";
}
static string IndexerDefinition(string dataSourceName, string indexName)
{
return #"
{
""description"": ""indexer for azure sql datasource"",
""dataSourceName"": """ + dataSourceName + #""",
""targetIndexName"": """ + indexName + #""",
""schedule"": { ""interval"": ""P1D"" }
}
";
}
}
The indexer is scheduled to run once per day. You can set it to run more frequently if the data changes often, but it might affect your search throughput.
This is the table definition if you're interested
CREATE TABLE [dbo].[testtable](
[id] [int] IDENTITY(1,1) NOT NULL,
[field1] [nchar](10) NULL,
[field2] [nchar](10) NULL,
[field3] [int] NULL,
[highwatermark] [timestamp] NOT NULL,
[deleted] [bit] NOT NULL
) ON [PRIMARY]
INSERT INTO [dbo].[testtable] (field1, field2, field3, deleted) VALUES ('abc', 'def', 123, 0)

It looks like you're trying to modify your index definition, but the body of the request contains the api-key instead of the JSON for the index definition. The api-key needs to be in the request headers, not the body.
You might find it simpler to use the Azure Search .NET SDK instead of calling the REST API directly.

Related

Renew SAS token used by Azure Iot Hub DeviceClient

How to renew SASToken which is generated and valid for one hour given the code below?
I cannot see any method to renew the SAS token.
public class IotHubService
{
Microsoft.Azure.Devices.Client.DeviceClient _deviceClient;
public void InitDeviceClient()
{
var sasToken = CreateOrRenewIotSasToken();
_deviceClient = DeviceClient.Create(_iotHubEndpoint,
new DeviceAuthenticationWithToken(deviceId, sasToken),
TransportType.Mqtt_WebSocket_Only);
_deviceClient.SetRetryPolicy(retryPolicy);
// Set handlers and callbacks
_deviceClient.SetConnectionStatusChangesHandler(ConnectionStatusChanged);
_iotHubCancellationTokenSource = new CancellationTokenSource();
await _deviceClient.OpenAsync(_iotHubCancellationTokenSource.Token);
}
public async Task<string> CreateOrRenewIotSasToken()
{
var iotHubEndpoint = AppConfig.IotHubEndpoint;
var deviceId = await GetDeviceIdAsync();
var sharedKey = _appConfigProvider.AppConfig.SharedKey;
var symmetricKey = _symmetricKeyProvider.GenerateSymmetricKey(deviceId, sharedKey);
_iotSasToken = GenerateSasToken(iotHubEndpoint, symmetricKey, null,3600);
return _iotSasToken;
}
public string GenerateSasToken(string resourceUri, string key, string policyName, int expiryInSeconds)
{
var fromEpochStart = _dateTimeProvider.GetUtcDateTime() - new DateTime(1970, 1, 1);
var expiry = $"{fromEpochStart.TotalSeconds + expiryInSeconds}";
var stringToSign = WebUtility.UrlEncode(resourceUri) + "\n" + expiry;
var hmac = new HMACSHA256(Convert.FromBase64String(key));
var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
var token = String.Format(CultureInfo.InvariantCulture, "SharedAccessSignature sr={0}&sig={1}&se={2}", WebUtility.UrlEncode(resourceUri), WebUtility.UrlEncode(signature), expiry);
if (!String.IsNullOrEmpty(policyName))
{
token += "&skn=" + policyName;
}
return token;
}
}
Microsoft.Azure.Devices.Client: 1.21.0

How do I use the rabbitmq in my .net core web

As the title suggests,Examples on the official website are console project but is it really impossible to apply to asp.net core web?
My web project as a consumer or producer but does not output received information,But the rabbitmq page console displays the queue messages sent,so What are consumers or producer in the actual production environment?windows server?console?
this is my api code:
[HttpGet]
public ActionResult sendMgs()
{
string message = string.Empty;
//var uri = new Uri("amqp://192.168.150.129:5672");
var factory = new ConnectionFactory()
{
UserName = "admin",
Password = "admin",
Port=5672,
HostName= "192.168.150.129",
RequestedHeartbeat = 0,
VirtualHost= "/vhost_mmr"
//Endpoint = new AmqpTcpEndpoint(uri)
};
using (var connection=factory.CreateConnection())
{
using (var channel = connection.CreateModel())
{
channel.QueueDeclare(queue:"hello",
durable:false,
exclusive:false,
autoDelete:false,
arguments:null);
message = "Hello World";
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(exchange: "",
routingKey:"hello",
basicProperties:null,
body:body);
}
}
return Json(new {message = message });
}
and this my mvc web code:
public IActionResult MqTest()
{
System.Diagnostics.Debug.Write("test begin:");
GetQueueMsg();
return View();
}
public void GetQueueMsg()
{
var factory = new ConnectionFactory()
{
UserName = "admin",
Password = "admin",
Port = 5672,
HostName = "192.168.150.129",
RequestedHeartbeat = 0,
VirtualHost = "/vhost_mmr"
};
using (var connection = factory.CreateConnection())
{
using (var channel =connection.CreateModel())
{
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
var body = ea.Body;
var msg = Encoding.UTF8.GetString(body);
ViewBag.msg = msg;
System.Diagnostics.Debug.Write("test:" + msg);
};
var ret = channel.BasicConsume(queue: "hello",
autoAck: true,
consumer: consumer);
}
}
}

Fetching data from Azure Cosmos DB in Flutter?

I wrote a function to fetch data using query from Azure Cosmos Database in Flutter/Dart, however it's giving error :
response.body: {"code":"BadRequest","message":"Message: {\"Errors\":[\"The input content is invalid because the required properties - 'æ©; ' - are missing\"]}\r\nActivityId: f75a0c6e-2c8d-4f13-a020-6e3c13fa5458, Request URI: /apps/f4533d11-81e3-4512-b639-0f0475c10611/services/401c9130-a85e-46a6-8311-c2dc8e5070d6/partitions/b5d2a58d-1304-414b-92c7-10e7fa95f679/replicas/131768862196689298p, RequestStats: , SDK: Microsoft.Azure.Documents.Common/2.0.0.0"}
I/flutter ( 5284): response.status: 400
Here is my piece of code
final response = await http.post(
endpointResource,
// Query
body: query,
// Post new message
headers: {
HttpHeaders.AUTHORIZATION: authToken,
HttpHeaders.CONTENT_TYPE: "application/query+json",
//'content-type': 'application/json',
'Accept': 'application/json',
//c.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
'x-ms-version': '2017-02-22',
'x-ms-date': date,
'x-ms-documentdb-isquery': 'true',
'x-ms-query-enable-crosspartition': 'true',
'x-ms-documentdb-query-enable-scan': 'true',
},
);
What should I do to get data back?
I managed to translate a code snippet from a working example in Javascript to Dart.
import 'dart:io';
import 'dart:convert';
import 'dart:async';
import 'dart:core';
import 'package:crypto/crypto.dart';
import 'package:hex/hex.dart';
class Cosmos{
String documentDBMasterKey;
Cosmos({this.documentDBMasterKey});
Future queryCosmos({url, method, body}) async{
String auth;
String documentDBMasterKey = this.documentDBMasterKey;
print("mastKey: $documentDBMasterKey");
method = method.trim(); //GET, POST, PUT or DEL
url = url.trim();
String utcString = HttpDate.format(DateTime.now());
print('RFC1123time: $utcString');
print('request url = ' + url);
String strippedurl =
url.replaceAllMapped(RegExp(r'^https?://[^/]+/'), (match) {
return '/';
});
print('stripped Url: $strippedurl');
List strippedparts = strippedurl.split('/');
int truestrippedcount = strippedparts.length - 1;
print('$truestrippedcount');
String resourceId;
String resType;
if (truestrippedcount % 2 != 0){
print('odd');
resType = strippedparts[truestrippedcount];
print('$resType');
if (truestrippedcount > 1){
int lastPart = strippedurl.lastIndexOf('/');
resourceId = strippedurl.substring(1, lastPart);
print('ResourceId: ' + resourceId);
}
}
else{
print('even');
resType = strippedparts[truestrippedcount -1];
print('resType: $resType');
strippedurl = strippedurl.substring(1);
print('strippedurl $strippedurl');
resourceId = strippedurl;
print('ResourceId: ' + resourceId);
}
String verb = method.toLowerCase();
String date = utcString.toLowerCase();
Base64Codec base64 = const Base64Codec();
var key = base64.decode(documentDBMasterKey); //Base64Bits --> BITS
print('key = ${HEX.encode(key)}');
print('masterKey = $documentDBMasterKey');
String text = (verb ?? '').toLowerCase() + '\n' +
(resType ?? '').toLowerCase() + '\n' +
(resourceId ?? '') + '\n' +
(date ?? '').toLowerCase() + '\n' +
'' + '\n';
print('text: $text');
var hmacSha256 = Hmac(sha256, key);
List<int> utf8Text = utf8.encode(text);
var hashSignature = hmacSha256.convert(utf8Text);
String base64Bits = base64.encode(hashSignature.bytes);
//Format our authentication token and URI encode it.
var masterToken = "master";
var tokenVersion = "1.0";
auth = Uri.encodeComponent('type=' + masterToken + '&ver=' + tokenVersion + '&sig=' + base64Bits);
print('auth= $auth');
Map<String, String> headers = {
'Accept': 'application/json',
'x-ms-version': '2016-07-11',
'Authorization': auth,
'x-ms-date': utcString,
'x-ms-documentdb-isquery' : 'true',
'Content-Type' : 'application/query+json',
'x-ms-documentdb-query-enablecrosspartition' : 'true',
};
Future<String> readResponse(HttpClientResponse response) {
final completer = Completer<String>();
final contents = StringBuffer();
response.transform(utf8.decoder).listen((data) {
contents.write(data);
}, onDone: () => completer.complete(contents.toString()));
return completer.future;
}
HttpClientRequest request;
HttpClient httpClient = new HttpClient();
if (method=='GET'){
request = await httpClient.getUrl(Uri.parse(url));
}
else if(method=='POST'){
request = await httpClient.postUrl(Uri.parse(url));
}
else if(method=='PUT'){
request = await httpClient.putUrl(Uri.parse(url));
}
else if(method=='DEL'){
request = await httpClient.deleteUrl(Uri.parse(url));
}
headers.forEach((key, value) {
request.headers.set(key,value);
});
if(body != null) {
request.add(utf8.encode(json.encode(body)));
}
HttpClientResponse aresponse = await request.close();
httpClient.close();
String aresponseString = await readResponse(aresponse);
return jsonDecode(aresponseString);
}
}
Just instantiate the class with your Cosmos Master Key:
Cosmos cosmos = Cosmos( documentDBMasterKey:'{your_cosmos_db_master_key}');
Query Cosmos Db by calling queryCosmos method. Pass 'url', 'method' and an optional 'body' as parameters:
// GET Example
() async {
Map<String, dynamic> get_dbs = await cosmos.queryCosmos(
url: 'https://{your_base_url}.documents.azure.com:443/dbs', method: 'GET');
print(get_dbs);
}
// POST Example (Query)
() async {
final Map<String, dynamic> body = {
"query":
"SELECT * FROM Faults f WHERE f.FaultId = #faultId",
"parameters": [
{"name": "#faultId", "value": 306000}
]
};
Map<String, dynamic> get_fault = await cosmos.queryCosmos(
url:
'https://{your_base_url}.documents.azure.com:443/dbs/{your_db}/colls/{your_collection}/docs',
method: 'POST',
body: body);
print('Get fault $get_fault');
}
Original code (JavaScript - Download to Postman and check pre-req script): https://github.com/MicrosoftCSA/documentdb-postman-collection
My code (dart): https://github.com/fvarela/cosmos_db_dart
I've created a Dart library to fetch data from a CosmosDB. For example to fetch documents from a collection you can just call this function:
import 'package:cosmosdb/cosmosdb.dart';
void main() {
final cosmosDB = CosmosDB(
masterKey: '<YOUR_MASTER_KEY>',
baseUrl: '<YOUR_BASE_URL>',
);
// get all documents from a collection
final documents = cosmosDB.documents.list('<YOUR_DATABASE>', '<YOUR_COLLECTION>');
print(documents);
}
GitHub: https://github.com/jonasfranz/cosmosdb
Package: https://pub.dev/packages/cosmosdb

Azure Blob Get Storage Get all Blobs using http request facing 403 forbidden error

I want to get all blob containers from azure storage using http client request.
I did one sample but i am facing forbidden 403 error.
I attached my code,
private const string ListofContainersURL = "https://{0}.blob.core.windows.net/?comp=list&maxresults=3"; //https://myaccount.blob.core.windows.net/?comp=list&maxresults=3
public string ListofContainersinBlob()
{
string Requesturl = string.Format(ListofContainersURL, storageAccount );
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Requesturl);
string now = DateTime.UtcNow.ToString("R");
request.Method = "GET";
request.Headers.Add("x-ms-version", "2015-12-11");
request.Headers.Add("x-ms-date", now);
request.Headers.Add("Authorization", AuthorizationHeader1("GET", now, request, storageAccount, storageKey));
var response = request.GetResponseAsync();
using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
{
return resp.StatusCode.ToString();
}
}
private string AuthorizationHeader1(string method, string now, HttpWebRequest request, string storageAccount, string storageKey)
{
string headerResource = $"x-ms-blob-type:BlockBlob\nx-ms-date:{now}\nx-ms-version:2015-12-11";
string urlResource = $"/{storageAccount}";
String AuthorizationHeader = String.Format("{0} {1}:{2}", "SharedKey", storageAccount, storageKey);
return AuthorizationHeader;
}
There are some issues with your AuthorizationHeader1 method. Please refer to Authentication for the Azure Storage Services for instructions on how to construct authorization header. Please try this code:
private static string AuthorizationHeader1(string method, string now, HttpWebRequest request, string storageAccount, string storageKey)
{
string headerResource = $"x-ms-date:{now}\nx-ms-version:2015-12-11";
string canonicalizedResource = $"/{storageAccount}/\ncomp:list\nmaxresults:3";
var contentEncoding = "";
var contentLanguage = "";
var contentLength = "";
var contentMd5 = "";
var contentType = "";
var date = "";
var ifModifiedSince = "";
var ifMatch = "";
var ifNoneMatch = "";
var ifUnmodifiedSince = "";
var range = "";
var stringToSign = $"{method}\n{contentEncoding}\n{contentLanguage}\n{contentLength}\n{contentMd5}\n{contentType}\n{date}\n{ifModifiedSince}\n{ifMatch}\n{ifNoneMatch}\n{ifUnmodifiedSince}\n{range}\n{headerResource}\n{canonicalizedResource}";
var signature = "";
using (var hmacSha256 = new HMACSHA256(Convert.FromBase64String(storageKey)))
{
var dataToHmac = Encoding.UTF8.GetBytes(stringToSign);
signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
}
String AuthorizationHeader = String.Format("{0} {1}:{2}", "SharedKey", storageAccount, signature);
return AuthorizationHeader;
}

Unauthorized Http Response

I am using an Azure Authentication in my Xamarin.Form project, the token received is used for making API calls for authentication purpose.
After some time after the keeping the app in background, again I try to make the API calls it returns "unauthorised".
The token expiration time is set to 30 min. But unauthorised error is not consistent some time it happens as soon as keep the app in background and some time it works fine.
Has anyone faced the same issue.
public async Task<Response> AuthenticatedGet(string uri, string accessToken, string content = null)
{
Uri restUri = new Uri(uri, UriKind.RelativeOrAbsolute);
HttpClient client = new HttpClient();
client.Timeout = TimeSpan.FromSeconds(60);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, restUri.ToString());
request.Headers.Add("Accept", "application/json");
request.Headers.Add("Authorization",
string.Format("Bearer {0}", accessToken));
var result = await client.SendAsync(request);
//HttpClient client = new HttpClient();
//client.Timeout = TimeSpan.FromSeconds(60);
//var result = await client.SendAsync(request);
Response sr = new Response();
if (result.IsSuccessStatusCode)
{
string responseString = await result.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(responseString))
{
sr.ResponseData = responseString;
sr.IsSuccess = true;
sr.StatusCode = (int)result.StatusCode;
}
}
else if (result.StatusCode == HttpStatusCode.NotFound)
{
sr.ResponseData = $"Service not found at the specifed uri {uri}";
sr.IsSuccess = false;
sr.StatusCode = (int)result.StatusCode;
}
else
{
//var responseString = await result.Content.ReadAsStringAsync();
//JObject jObject = JObject.Parse(responseString);
//var messageProperty = jObject.Property("Message");
//if (messageProperty != null && result.StatusCode == HttpStatusCode.Unauthorized)
//{
// var message = messageProperty.Value?.ToString();
// sr.Message = !string.IsNullOrEmpty(message) ? message : result.ReasonPhrase;
// LogoutUnauthorisedUser?.Invoke(message);
// throw new UnauthorizedAccessException(message);
//}
//sr.Message = result.ReasonPhrase;
//sr.IsSuccess = false;
//sr.StatusCode = (int)result.StatusCode;
//TODO: Handle Unauthorized user
}
return sr;
}
public async Task<ObservableCollection<NIODetails>> GetABCServiceAsync()
{
var uri = string.Format(_hostConfiguration.ABCHostName + _hostConfiguration.ABC, Configuration.ABC);
var resonse = await _httpService.AuthenticatedGet(uri, Constant.ADToken, null);
if (resonse.IsSuccess)
{
var list = JsonConvert.DeserializeObject<ObservableCollection<ABCDetails>>(resonse.ResponseData);
return list;
}
else
{
return null;
}
}

Resources