diff --git a/DotNetHowToEncryptionUsingCMK/DotNetHowToEncryptionUsingCMK/DotNetHowToEncryptionUsingCMK.csproj b/DotNetHowToEncryptionUsingCMK/DotNetHowToEncryptionUsingCMK/DotNetHowToEncryptionUsingCMK.csproj
index 7ba7640..b13e9f5 100644
--- a/DotNetHowToEncryptionUsingCMK/DotNetHowToEncryptionUsingCMK/DotNetHowToEncryptionUsingCMK.csproj
+++ b/DotNetHowToEncryptionUsingCMK/DotNetHowToEncryptionUsingCMK/DotNetHowToEncryptionUsingCMK.csproj
@@ -6,8 +6,9 @@
-
+
+
diff --git a/DotNetHowToEncryptionUsingCMK/DotNetHowToEncryptionUsingCMK/Hotel.cs b/DotNetHowToEncryptionUsingCMK/DotNetHowToEncryptionUsingCMK/Hotel.cs
index aea181d..cc9f6c0 100644
--- a/DotNetHowToEncryptionUsingCMK/DotNetHowToEncryptionUsingCMK/Hotel.cs
+++ b/DotNetHowToEncryptionUsingCMK/DotNetHowToEncryptionUsingCMK/Hotel.cs
@@ -1,56 +1,52 @@
-namespace AzureSearch.SDKHowTo
+using System;
+using Microsoft.Spatial;
+using Azure.Search.Documents.Indexes;
+using Azure.Search.Documents.Indexes.Models;
+using System.Text.Json.Serialization;
+
+namespace AzureSearch.SDKHowTo
{
- using System;
- using Microsoft.Azure.Search;
- using Microsoft.Azure.Search.Models;
- using Microsoft.Spatial;
- using Newtonsoft.Json;
-
- // The SerializePropertyNamesAsCamelCase attribute is defined in the Azure Search .NET SDK.
- // It ensures that Pascal-case property names in the model class are mapped to camel-case
+
+
+ // The JsonPropertyName attribute is defined in the Azure Search .NET SDK.
+ // Here it used to ensure that Pascal-case property names in the model class are mapped to camel-case
// field names in the index.
- [SerializePropertyNamesAsCamelCase]
public partial class Hotel
{
- [System.ComponentModel.DataAnnotations.Key]
- [IsFilterable]
+ [SimpleField(IsKey = true, IsFilterable = true)]
public string HotelId { get; set; }
- [IsFilterable, IsSortable, IsFacetable]
+ [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
public double? BaseRate { get; set; }
- [IsSearchable]
+ [SearchableField]
public string Description { get; set; }
- [IsSearchable]
- [Analyzer(AnalyzerName.AsString.FrLucene)]
- [JsonProperty("description_fr")]
+ [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.FrLucene)]
public string DescriptionFr { get; set; }
- [IsSearchable, IsFilterable, IsSortable]
+ [SearchableField(IsFilterable = true, IsSortable = true)]
public string HotelName { get; set; }
- [IsSearchable, IsFilterable, IsSortable, IsFacetable]
- [SynonymMaps("desc-synonymmap")]
+ [SearchableField(IsFilterable = true, IsFacetable = true, IsSortable = true)]
public string Category { get; set; }
- [IsSearchable, IsFilterable, IsFacetable]
- [SynonymMaps("desc-synonymmap")]
+ [SearchableField(IsFilterable = true, IsFacetable = true)]
public string[] Tags { get; set; }
- [IsFilterable, IsFacetable]
+ [SimpleField(IsFilterable = true, IsFacetable = true)]
public bool? ParkingIncluded { get; set; }
- [IsFilterable, IsFacetable]
+ [SimpleField(IsFilterable = true, IsFacetable = true)]
public bool? SmokingAllowed { get; set; }
- [IsFilterable, IsSortable, IsFacetable]
+ [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
public DateTimeOffset? LastRenovationDate { get; set; }
- [IsFilterable, IsSortable, IsFacetable]
+ [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
public int? Rating { get; set; }
- [IsFilterable, IsSortable]
+ [SimpleField(IsFilterable = true, IsSortable = true)]
public GeographyPoint Location { get; set; }
}
}
diff --git a/DotNetHowToEncryptionUsingCMK/DotNetHowToEncryptionUsingCMK/Program.cs b/DotNetHowToEncryptionUsingCMK/DotNetHowToEncryptionUsingCMK/Program.cs
index 7c6204c..7ac537f 100644
--- a/DotNetHowToEncryptionUsingCMK/DotNetHowToEncryptionUsingCMK/Program.cs
+++ b/DotNetHowToEncryptionUsingCMK/DotNetHowToEncryptionUsingCMK/Program.cs
@@ -1,15 +1,18 @@
#define HowToExample
+using System;
+using System.Linq;
+using System.Threading;
+using Azure;
+using Azure.Search.Documents;
+using Azure.Search.Documents.Indexes;
+using Azure.Search.Documents.Indexes.Models;
+using Azure.Search.Documents.Models;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Spatial;
+
namespace AzureSearch.SDKHowTo
{
- using System;
- using System.Linq;
- using System.Threading;
- using Microsoft.Azure.Search;
- using Microsoft.Azure.Search.Models;
- using Microsoft.Extensions.Configuration;
- using Microsoft.Spatial;
-
class Program
{
// This sample shows how to create a synonym-map and an index that are encrypted with customer-managed key in Azure Key Vault
@@ -18,206 +21,207 @@ static void Main(string[] args)
IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile("appsettings.json");
IConfigurationRoot configuration = builder.Build();
- SearchServiceClient serviceClient = CreateSearchServiceClient(configuration);
+ SearchIndexClient indexClient = CreateSearchIndexClient(configuration);
Console.WriteLine("Cleaning up resources...\n");
- CleanupResources(serviceClient);
+ CleanupResources(indexClient);
Console.WriteLine("Creating synonym-map encrypted with customer managed key...\n");
- CreateSynonymsEncryptedUsingCustomerManagedKey(serviceClient, configuration);
+ CreateSynonymsEncryptedUsingCustomerManagedKey(indexClient, configuration);
Console.WriteLine("Creating index encrypted with customer managed key...\n");
- CreateHotelsIndexEncryptedUsingCustomerManagedKey(serviceClient, configuration);
+ CreateHotelsIndexEncryptedUsingCustomerManagedKey(indexClient, configuration);
- ISearchIndexClient indexClient = serviceClient.Indexes.GetClient("hotels");
+ SearchIndex index = indexClient.GetIndex("hotels");
+ index = AddSynonymMapsToFields(index);
+ indexClient.CreateOrUpdateIndex(index);
+
+ SearchClient searchClient = indexClient.GetSearchClient("hotels");
Console.WriteLine("Uploading documents...\n");
- UploadDocuments(indexClient);
+ UploadDocuments(searchClient);
- ISearchIndexClient indexClientForQueries = CreateSearchIndexClient(configuration);
+ SearchClient searchClientForQueries = CreateSearchClient(configuration);
- RunQueries(indexClientForQueries);
+ RunQueries(searchClientForQueries);
Console.WriteLine("Complete. Press any key to end application...\n");
Console.ReadKey();
}
- private static SearchServiceClient CreateSearchServiceClient(IConfigurationRoot configuration)
+ private static SearchIndexClient CreateSearchIndexClient(IConfigurationRoot configuration)
{
- string searchServiceName = configuration["SearchServiceName"];
+ string searchServiceEndPoint = configuration["SearchServiceEndPoint"];
string adminApiKey = configuration["SearchServiceAdminApiKey"];
- SearchServiceClient serviceClient = new SearchServiceClient(searchServiceName, new SearchCredentials(adminApiKey));
- return serviceClient;
+ SearchIndexClient indexClient = new SearchIndexClient(new Uri(searchServiceEndPoint), new AzureKeyCredential(adminApiKey));
+ return indexClient;
}
- private static SearchIndexClient CreateSearchIndexClient(IConfigurationRoot configuration)
+ private static SearchClient CreateSearchClient(IConfigurationRoot configuration)
{
- string searchServiceName = configuration["SearchServiceName"];
+ string searchServiceEndPoint = configuration["SearchServiceEndPoint"];
string queryApiKey = configuration["SearchServiceQueryApiKey"];
- SearchIndexClient indexClient = new SearchIndexClient(searchServiceName, "hotels", new SearchCredentials(queryApiKey));
- return indexClient;
+ SearchClient searchClient = new SearchClient(new Uri(searchServiceEndPoint), "hotels", new AzureKeyCredential(queryApiKey));
+ return searchClient;
}
- private static void CleanupResources(SearchServiceClient serviceClient)
+ private static void CleanupResources(SearchIndexClient indexClient)
{
- if (serviceClient.Indexes.Exists("hotels"))
+ try
{
- serviceClient.Indexes.Delete("hotels");
+ if (indexClient.GetIndex("hotels") != null)
+ {
+ indexClient.DeleteIndex("hotels");
+ }
+ if (indexClient.GetSynonymMapNames().Value.Contains("desc-synonymmap"))
+ {
+ indexClient.DeleteSynonymMap("desc-synonymmap");
+ }
}
-
- if (serviceClient.SynonymMaps.Exists("desc-synonymmap"))
+ catch (RequestFailedException e) when (e.Status == 404)
{
- serviceClient.SynonymMaps.Delete("desc-synonymmap");
+ //if exception occurred and status is "Not Found", this is work as expect
+ Console.WriteLine("Failed to find index and this is because it's not there.");
}
}
- private static void CreateSynonymsEncryptedUsingCustomerManagedKey(SearchServiceClient serviceClient, IConfigurationRoot configuration)
+ private static void CreateSynonymsEncryptedUsingCustomerManagedKey(SearchIndexClient indexClient, IConfigurationRoot configuration)
{
- var synonymMap = new SynonymMap()
+ var synonymMap = new SynonymMap("desc-synonymmap", "hotel, motel\ninternet,wifi\nfive star=>luxury\neconomy,inexpensive=>budget")
{
- Name = "desc-synonymmap",
- Synonyms = "hotel, motel\ninternet,wifi\nfive star=>luxury\neconomy,inexpensive=>budget",
EncryptionKey = GetEncryptionKeyFromConfiguration(configuration)
};
- serviceClient.SynonymMaps.CreateOrUpdate(synonymMap);
+ indexClient.CreateOrUpdateSynonymMap(synonymMap);
+ }
+
+ private static SearchIndex AddSynonymMapsToFields(SearchIndex index)
+ {
+ //remove SynonymMaps attribute in class hotel, need Add maps manually.
+ index.Fields.First(f => f.Name == "Category").SynonymMapNames.Add("desc-synonymmap");
+ index.Fields.First(f => f.Name == "Tags").SynonymMapNames.Add("desc-synonymmap");
+ return index;
}
- private static void CreateHotelsIndexEncryptedUsingCustomerManagedKey(SearchServiceClient serviceClient, IConfigurationRoot configuration)
+ private static void CreateHotelsIndexEncryptedUsingCustomerManagedKey(SearchIndexClient indexClient, IConfigurationRoot configuration)
{
- var definition = new Index()
+ FieldBuilder fieldBuilder = new FieldBuilder();
+ var searchFields = fieldBuilder.Build(typeof(Hotel));
+ var definition = new SearchIndex("hotels", searchFields)
{
- Name = "hotels",
- Fields = FieldBuilder.BuildForType(),
EncryptionKey = GetEncryptionKeyFromConfiguration(configuration)
};
- serviceClient.Indexes.Create(definition);
+ indexClient.CreateOrUpdateIndex(definition);
}
- private static EncryptionKey GetEncryptionKeyFromConfiguration(IConfigurationRoot configuration)
+ private static SearchResourceEncryptionKey GetEncryptionKeyFromConfiguration(IConfigurationRoot configuration)
{
Uri keyVaultKeyUri = new Uri(configuration["AzureKeyVaultKeyIdentifier"]);
+
if (!keyVaultKeyUri.Host.Contains("vault.azure.net") || keyVaultKeyUri.Segments.Length != 4 || keyVaultKeyUri.Segments[1] != "keys/")
{
throw new ArgumentException("Invalid 'AzureKeyVaultKeyIdentifier' - Expected format: 'https://.vault.azure.net/keys//'", "AzureKeyVaultKeyIdentifier");
}
- var encryptionKey = new EncryptionKey
- {
- KeyVaultUri = $"{keyVaultKeyUri.Scheme}://{keyVaultKeyUri.Host}",
- KeyVaultKeyName = keyVaultKeyUri.Segments[2].Trim('/'),
- KeyVaultKeyVersion = keyVaultKeyUri.Segments[3].Trim('/')
- };
-
+ SearchResourceEncryptionKey encryptionKey = null;
string applicationId = configuration["AzureActiveDirectoryApplicationId"];
if (!string.IsNullOrWhiteSpace(applicationId))
{
- encryptionKey.AccessCredentials = new AzureActiveDirectoryApplicationCredentials
+ encryptionKey = new SearchResourceEncryptionKey(new Uri($"{keyVaultKeyUri.Scheme}://{keyVaultKeyUri.Host}"), keyVaultKeyUri.Segments[2].Trim('/'), keyVaultKeyUri.Segments[3].Trim('/'))
{
ApplicationId = applicationId,
ApplicationSecret = configuration["AzureActiveDirectoryApplicationSecret"]
};
}
- encryptionKey.Validate();
+
return encryptionKey;
}
- private static void UploadDocuments(ISearchIndexClient indexClient)
+ private static void UploadDocuments(SearchClient searchClient)
{
- var hotels = new Hotel[]
- {
- new Hotel()
- {
- HotelId = "1",
- BaseRate = 199.0,
- Description = "Best hotel in town",
- DescriptionFr = "Meilleur hôtel en ville",
- HotelName = "Fancy Stay",
- Category = "Luxury",
- Tags = new[] { "pool", "view", "wifi", "concierge" },
- ParkingIncluded = false,
- SmokingAllowed = false,
- LastRenovationDate = new DateTimeOffset(2010, 6, 27, 0, 0, 0, TimeSpan.Zero),
- Rating = 5,
- Location = GeographyPoint.Create(47.678581, -122.131577)
- },
- new Hotel()
- {
- HotelId = "2",
- BaseRate = 79.99,
- Description = "Cheapest hotel in town",
- DescriptionFr = "Hôtel le moins cher en ville",
- HotelName = "Roach Motel",
- Category = "Budget",
- Tags = new[] { "motel", "budget" },
- ParkingIncluded = true,
- SmokingAllowed = true,
- LastRenovationDate = new DateTimeOffset(1982, 4, 28, 0, 0, 0, TimeSpan.Zero),
- Rating = 1,
- Location = GeographyPoint.Create(49.678581, -122.131577)
- },
- new Hotel()
- {
- HotelId = "3",
- BaseRate = 129.99,
- Description = "Close to town hall and the river"
- }
- };
-
- var batch = IndexBatch.Upload(hotels);
-
+ IndexDocumentsBatch batch = IndexDocumentsBatch.Create(
+ IndexDocumentsAction.Upload(
+ new Hotel()
+ {
+ HotelId = "1",
+ BaseRate = 199.0,
+ Description = "Best hotel in town",
+ DescriptionFr = "Meilleur hôtel en ville",
+ HotelName = "Fancy Stay",
+ Category = "Luxury",
+ Tags = new[] { "pool", "view", "wifi", "concierge" },
+ ParkingIncluded = false,
+ SmokingAllowed = false,
+ LastRenovationDate = new DateTimeOffset(2010, 6, 27, 0, 0, 0, TimeSpan.Zero),
+ Rating = 5,
+ Location = GeographyPoint.Create(47.678581, -122.131577)
+ }),
+ IndexDocumentsAction.Upload(
+ new Hotel()
+ {
+ HotelId = "2",
+ BaseRate = 79.99,
+ Description = "Cheapest hotel in town",
+ DescriptionFr = "Hôtel le moins cher en ville",
+ HotelName = "Roach Motel",
+ Category = "Budget",
+ Tags = new[] { "motel", "budget" },
+ ParkingIncluded = true,
+ SmokingAllowed = true,
+ LastRenovationDate = new DateTimeOffset(1982, 4, 28, 0, 0, 0, TimeSpan.Zero),
+ Rating = 1,
+ Location = GeographyPoint.Create(49.678581, -122.131577)
+ }));
try
{
- indexClient.Documents.Index(batch);
+ IndexDocumentsResult result = searchClient.IndexDocuments(batch);
}
- catch (IndexBatchException e)
+ catch (Exception)
{
// Sometimes when your Search service is under load, indexing will fail for some of the documents in
// the batch. Depending on your application, you can take compensating actions like delaying and
// retrying. For this simple demo, we just log the failed document keys and continue.
- Console.WriteLine(
- "Failed to index some of the documents: {0}",
- String.Join(", ", e.IndexingResults.Where(r => !r.Succeeded).Select(r => r.Key)));
+ Console.WriteLine("Failed to index some of the documents: {0}");
}
Console.WriteLine("Waiting for documents to be indexed...\n");
Thread.Sleep(2000);
}
- private static void RunQueries(ISearchIndexClient indexClient)
+ private static void RunQueries(SearchClient searchClient)
{
- SearchParameters parameters;
- DocumentSearchResult results;
+ SearchOptions searchOptions;
+ SearchResults results;
Console.WriteLine("Search with terms nonexistent in the index:\n");
- parameters =
- new SearchParameters()
- {
- SearchFields = new[] { "category", "tags" },
- Select = new[] { "hotelName", "category", "tags" },
- };
+ searchOptions = new SearchOptions();
+ searchOptions.SearchFields.Add("Category");
+ searchOptions.SearchFields.Add("Tags");
+ searchOptions.Select.Add("HotelName");
+ searchOptions.Select.Add("Category");
+ searchOptions.Select.Add("Tags");
Console.WriteLine("Search the entire index for the phrase \"five star\":\n");
- results = indexClient.Documents.Search("\"five star\"", parameters);
+ results = searchClient.Search("\"five star\"", searchOptions);
WriteDocuments(results);
Console.WriteLine("Search the entire index for the term 'internet':\n");
- results = indexClient.Documents.Search("internet", parameters);
+ results = searchClient.Search("internet", searchOptions);
WriteDocuments(results);
Console.WriteLine("Search the entire index for the terms 'economy' AND 'hotel':\n");
- results = indexClient.Documents.Search("economy AND hotel", parameters);
+ results = searchClient.Search("economy AND hotel", searchOptions);
WriteDocuments(results);
}
- private static void WriteDocuments(DocumentSearchResult searchResults)
+ private static void WriteDocuments(SearchResults searchResults)
{
- foreach (SearchResult result in searchResults.Results)
+ foreach (SearchResult result in searchResults.GetResults())
{
Console.WriteLine(result.Document);
}