LUIS Programmatic APIs v2.0 Helper

LUIS Service Docs
LUIS Service REST

  最近的项目中使用了微软认知服务系列提供的Language Understanding (LUIS)服务。 鉴于每次调整LUIS都需要到luis.ai进行相关调整感觉很麻烦。 于是将LUIS提供的REST API封装为LUIS Services Helper以供项目自身调用。

Model:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
namespace KnowledgeBot.Portal.Service.Luis.Model    
{    
    public class Entity    
    {    
        public string Id { getset; }    
        public string Name { getset; }    
        public long TypeId { getset; }    
        public string ReadableType { getset; }    
    }    
}    

using System.Collections.Generic;    

namespace KnowledgeBot.Portal.Service.Luis.Model    
{    
    public class Example    
    {    
        public string Text { getset; }    
        public string IntentName { getset; }    
        public IEnumerable<EntityLabel> EntityLabels { getset; }    
    }    

    public class JSONExample    
    {    
        public string Text { getset; }    
        public string Intent { getset; }    
        public IEnumerable<EntityLabel> Entities { getset; }    
    }    

    public class EntityLabel    
    {    
        public string EntityName { getset; }    
        public int StartCharIndex { getset; }    
        public int EndCharIndex { getset; }    
    }    
}    

namespace KnowledgeBot.Portal.Service.Luis.Model    
{    
    public class Intent    
    {    
        public string Id { getset; }    
        public string Name { getset; }    
    }    
}    

using System;    

namespace KnowledgeBot.Portal.Service.Luis.Model    
{    
    public class LuisApp    
    {    
        public string Id { getset; }    
        public string Name { getset; }    
        public string Description { getset; }    
        public string Culture { getset; }    
        public string UsageScenario { getset; }    
        public string Domain { getset; }    
        public int VersionsCount { getset; }    
        public DateTime CreatedDateTime { getset; }    
        public Endpoints Endpoints { getset; }    
        public int EndpointHitsCount { getset; }    
    }    

    public class Endpoints    
    {    
        public Production Production { getset; }    
    }    

    public class Production    
    {    
        public string VersionId { getset; }    
        public bool IsStaging { getset; }    
        public string EndpointUrl { getset; }    
        public string EndpointRegion { getset; }    
        public string AssignedEndpointKey { getset; }    
        public string PublishedDateTime { getset; }    
    }    
}    

using Newtonsoft.Json;    

namespace KnowledgeBot.Portal.Service.Luis.Model    
{    
    public class Publish    
    {    
        public string EndpointUrl { getset; }    

        [JsonProperty(“subscription-key”)]    
        public string SubscriptionKey { getset; }    
        public string EndpointRegion { getset; }    
        public bool IsStaging { getset; }    
    }    
}    

using Newtonsoft.Json;    
using System;    

namespace KnowledgeBot.Portal.Service.Luis.Model    
{    
    publicclass Training    
    {    
        publicstring ModelId { getset; }    

        [JsonProperty(“details”)]    
        public TrainingDetails Details { getset; }    
    }    

    public class TrainingDetails    
    {    
        public int StatusId { getset; }    
        public string Status { getset; }    
        public int ExampleCount { getset; }    
        public DateTime? TrainingDateTime { getset; }    
        public string FailureReason { getset; }    
    }    
}    

namespace KnowledgeBot.Portal.Service.Luis.Model    
{    
    public class Utterance    
    {    
        public string UtteranceText { getset; }    
        public int ExampleId { getset; }    
    }    
}

ServiceClient:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
using Newtonsoft.Json;    
using Newtonsoft.Json.Serialization;    
using System;    
using System.Net.Http;    
using System.Net.Http.Headers;    
using System.Text;    
using System.Threading.Tasks;    
using System.Web.Configuration;    

namespace KnowledgeBot.Portal.Service.Luis    
{    
    public class ServiceClient    
    {    
        private string BASE_URL = WebConfigurationManager.AppSettings[“LuisAPIDomain”] ?? “https://westus.api.cognitive.microsoft.com/luis/api/v2.0”;  
        //private string BASE_URL = WebConfigurationManager.AppSettings[“LuisAPIDomain”] ?? “https://westus.api.cognitive.microsoft.com/luis/api/v2.0”;  
        private readonly string _subscriptionKey;    

        public ServiceClient(string subscriptionKey) =>    
            _subscriptionKey = subscriptionKey;    

        protected async Task<HttpResponseMessage> Get(string path)    
        {    
            using (var client = new HttpClient())    
            {    
                client.DefaultRequestHeaders.Add(“Ocp-Apim-Subscription-Key”, _subscriptionKey);    
                return await client.GetAsync($“{BASE_URL}{path}”);    
            }    
        }    

        protected async Task<stringPost(string path)    
        {    
            using (var client = new HttpClient())    
            {    
                client.DefaultRequestHeaders.Add(“Ocp-Apim-Subscription-Key”, _subscriptionKey);    
                var response = await client.PostAsync($“{BASE_URL}{path}”, null);    
                var responseContent = await response.Content.ReadAsStringAsync();    
                if (response.IsSuccessStatusCode)    
                    return responseContent;    
                else
                {    
                    var exception = JsonConvert.DeserializeObject<ServiceException>(responseContent);    
                    thrownew Exception($“{exception.Error?.Message ?? exception.Message}”);    
                }    
            }    
        }    

        protected async Task<string> Post<TRequest>(string path, TRequest requestBody)    
        {    
            using (var client = new HttpClient())    
            {    
                using (var content = new ByteArrayContent(GetByteData(requestBody)))    
                {    
                    client.DefaultRequestHeaders.Add(“Ocp-Apim-Subscription-Key”, _subscriptionKey);    
                    content.Headers.ContentType = new MediaTypeHeaderValue(“application/json”);    
                    var response = await client.PostAsync($“{BASE_URL}{path}”, content);    
                    var responseContent = await response.Content.ReadAsStringAsync();    
                    if (response.IsSuccessStatusCode)    
                        return responseContent;    
                    else
                    {    
                        var exception = JsonConvert.DeserializeObject<ServiceException>(responseContent);    
                        thrownew Exception($“{exception.Error?.Message ?? exception.Message}”);    
                    }    
                }    
            }    
        }    

        protected async Task Put<TRequest>(string path, TRequest requestBody)    
        {    
            using (var client = new HttpClient())    
            {    
                using (var content = new ByteArrayContent(GetByteData(requestBody)))    
                {    
                    client.DefaultRequestHeaders.Add(“Ocp-Apim-Subscription-Key”, _subscriptionKey);    
                    content.Headers.ContentType = new MediaTypeHeaderValue(“application/json”);    
                    var response = await client.PutAsync($“{BASE_URL}{path}”, content);    
                    if (!response.IsSuccessStatusCode)    
                    {    
                        var responseContent = await response.Content.ReadAsStringAsync();    
                        var exception = JsonConvert.DeserializeObject<ServiceException>(responseContent);    
                        thrownew Exception($“{exception.Error?.Message ?? exception.Message}”);    
                    }    
                }    
            }    
        }    

        protected async Task Delete(string path)    
        {    
            using (var client = new HttpClient())    
            {    
                client.DefaultRequestHeaders.Add(“Ocp-Apim-Subscription-Key”, _subscriptionKey);    
                var response = await client.DeleteAsync($“{BASE_URL}{path}”);    
                if (!response.IsSuccessStatusCode)    
                {    
                    var responseContent = await response.Content.ReadAsStringAsync();    
                    var exception = JsonConvert.DeserializeObject<ServiceException>(responseContent);    
                    thrownew Exception($“{exception.Error?.Message ?? exception.Message}”);    
                }    
            }    
        }    

        private byte[] GetByteData<TRequest>(TRequest requestBody)    
        {    
            var settings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };    
            var body = JsonConvert.SerializeObject(requestBody, settings);    
            return Encoding.UTF8.GetBytes(body);    
        }    
    }    
}

ServiceException:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace KnowledgeBot.Portal.Service.Luis    
{    
    publicclass ServiceException    
    {    
        public Error Error { getset; }    
        publicstring Message { getset; }    
    }    

    publicclass Error    
    {    
        publicstring Code { getset; }    
        publicstring Message { getset; }    
    }    
}

Interface:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
using KnowledgeBot.Portal.Service.Luis.Model;    
using System.Collections.Generic;    
using System.Threading.Tasks;    

namespace KnowledgeBot.Portal.Service.Luis    
{    
    public interface ILuisClientService    
    {    
        Task<IReadOnlyCollection<LuisApp>> GetAllAppsAsync();    
        Task<LuisApp> GetAppByIdAsync(string id);    
        Task<LuisApp> GetAppByNameAsync(string name);    
        Task<stringAddAppAsync(string name, string description, string culture, string usageScenario, string domain, string initialVersionId);    
        Task RenameAppAsync(string id, string name, string description);    
        Task DeleteAppAsync(string id);    

        Task<IReadOnlyCollection<Intent>> GetAllIntentsAsync(string appId, string appVersionId);    
        Task<Intent> GetIntentByIdAsync(string id, string appId, string appVersionId);    
        Task<Intent> GetIntentByNameAsync(string name, string appId, string appVersionId);    
        Task<stringAddIntentAsync(string name, string appId, string appVersionId);    
        Task RenameIntentAsync(string id, string name, string appId, string appVersionId);    
        Task DeleteIntentAsync(string id, string appId, string appVersionId);    

        Task<IReadOnlyCollection<Entity>> GetAllEntitiesAsync(string appId, string appVersionId);    
        Task<Entity> GetEntityByIdAsync(string id, string appId, string appVersionId);    
        Task<Entity> GetEntityByNameAsync(string name, string appId, string appVersionId);    
        Task<stringAddEntityAsync(string name, string appId, string appVersionId);    
        Task RenameEntityAsync(string id, string name, string appId, string appVersionId);    
        Task DeleteEntityAsync(string id, string appId, string appVersionId);    

        Task<Utterance> AddExampleAsync(string appId, string appVersionId, Example model);    

        Task<TrainingDetails> TrainAsync(string appId, string appVersionId);    
        Task<IEnumerable<Training>> GetTrainingStatusListAsync(string appId, string appVersionId);    

        Task<Publish> PublishAsync(string appId, string appVersionId, bool isStaging, string region);    
    }    
}

Interface implement:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
using KnowledgeBot.Portal.Service.Luis;    
using KnowledgeBot.Portal.Service.Luis.Model;    
using Newtonsoft.Json;    
using System;    
using System.Collections.Generic;    
using System.Linq;    
using System.Threading.Tasks;    

namespace KnowledgeBot.Portal.Service    
{    
    public class LuisClientService : ServiceClientILuisClientService    
    {    
        public LuisClientService(string subscriptionKey) : base(subscriptionKey) {    

        }    

        #region Apps  

        /// <summary>  
        /// Lists all of the user applications  
        /// </summary>  
        /// <returns>A List of LUIS apps</returns>  
        public async Task<IReadOnlyCollection<LuisApp>> GetAllAppsAsync()    
        {    
            var response = await Get($“/apps”);    
            var content = await response.Content.ReadAsStringAsync();    
            if (response.IsSuccessStatusCode)    
                return JsonConvert.DeserializeObject<IReadOnlyCollection<LuisApp>>(content);    
            elseif (response.StatusCode != System.Net.HttpStatusCode.BadRequest)    
            {    
                var exception = JsonConvert.DeserializeObject<ServiceException>(content);    
                thrownew Exception($“{exception.Error.Code} – {exception.Error.Message}”);    
            }    
            returnnull;    
        }    

        /// <summary>  
        /// Gets the application info  
        /// </summary>  
        /// <param name=”id”>app id</param>  
        /// <returns>LUIS app</returns>  
        public async Task<LuisApp> GetAppByIdAsync(string id)    
        {    
            var response = await Get($“/apps/{id}”);    
            var content = await response.Content.ReadAsStringAsync();    
            if (response.IsSuccessStatusCode)    
                return JsonConvert.DeserializeObject<LuisApp>(content);    
            elseif (response.StatusCode != System.Net.HttpStatusCode.BadRequest)    
            {    
                var exception = JsonConvert.DeserializeObject<ServiceException>(content);    
                thrownew Exception($“{exception.Error.Code} – {exception.Error.Message}”);    
            }    
            returnnull;    
        }    

        /// <summary>  
        /// Gets the application info  
        /// </summary>  
        /// <param name=”name”>app name</param>  
        /// <returns>LUIS app</returns>  
        public async Task<LuisApp> GetAppByNameAsync(string name)    
        {    
            var apps = await GetAllAppsAsync();    
            return apps.FirstOrDefault(app => app.Name.Equals(name));    
        }    

        /// <summary>  
        /// Creates a new LUIS app and returns the id  
        /// </summary>  
        /// <param name=”name”>app name</param>  
        /// <param name=”description”>app description</param>  
        /// <param name=”culture”>app culture: ‘en-us’, ‘es-es’, ‘pt-br’ and others</param>  
        /// <param name=”usageScenario”></param>  
        /// <param name=”domain”></param>  
        /// <param name=”initialVersionId”></param>  
        /// <returns>The ID of the created app</returns>  
        public async Task<stringAddAppAsync(string name, string description, string culture, string usageScenario, string domain, string initialVersionId)    
        {    
            var app = new
            {    
                name = name,    
                description = description,    
                culture = culture,    
                usageScenario = usageScenario,    
                domain = domain,    
                initialVersionId = initialVersionId    
            };    
            var response = await Post($“/apps”, app);    
            return JsonConvert.DeserializeObject<string>(response);    
        }    

        /// <summary>  
        /// Change the name and description of LUIS app  
        /// </summary>  
        /// <param name=”id”>app id</param>  
        /// <param name=”name”>new app name</param>  
        /// <param name=”description”>new app description</param>  
        /// <returns></returns>  
        public async Task RenameAppAsync(string id, string name, string description)    
        {    
            var app = new
            {    
                name = name,    
                description = description    
            };    
            await Put($“/apps/{id}”, app);    
        }    

        /// <summary>  
        /// Deletes an application  
        /// </summary>  
        /// <param name=”id”>app id</param>  
        /// <returns></returns>  
        public async Task DeleteAppAsync(string id)    
        {    
            await Delete($“/apps/{id}”);    
        }    

        #endregion  

        #region Intents  

        /// <summary>  
        /// Gets information about the intent models  
        /// </summary>  
        /// <param name=”appId”>app id</param>  
        /// <param name=”appVersionId”>app version</param>  
        /// <returns>A List of app intents</returns>  
        public async Task<IReadOnlyCollection<Intent>> GetAllIntentsAsync(string appId, string appVersionId)    
        {    
            var response = await Get($“/apps/{appId}/versions/{appVersionId}/intents”);    
            var content = await response.Content.ReadAsStringAsync();    
            if (response.IsSuccessStatusCode)    
                return JsonConvert.DeserializeObject<IReadOnlyCollection<Intent>>(content);    
            elseif (response.StatusCode != System.Net.HttpStatusCode.BadRequest)    
            {    
                var exception = JsonConvert.DeserializeObject<ServiceException>(content);    
                thrownew Exception($“{ exception.Error.Code} – { exception.Error.Message}”);    
            }    
            returnnull;    
        }    

        /// <summary>  
        /// Gets information about the intent model  
        /// </summary>  
        /// <param name=”id”>intent id</param>  
        /// <param name=”appId”>app id</param>  
        /// <param name=”appVersionId”>app version</param>  
        /// <returns>app intent</returns>  
        public async Task<Intent> GetIntentByIdAsync(string id, string appId, string appVersionId)    
        {    
            var response = await Get($“/apps/{appId}/versions/{appVersionId}/intents/{id}”);    
            var content = await response.Content.ReadAsStringAsync();    
            if (response.IsSuccessStatusCode)    
                return JsonConvert.DeserializeObject<Intent>(content);    
            elseif (response.StatusCode != System.Net.HttpStatusCode.BadRequest)    
            {    
                var exception = JsonConvert.DeserializeObject<ServiceException>(content);    
                thrownew Exception($“{ exception.Error.Code} – { exception.Error.Message}”);    
            }    
            returnnull;    
        }    

        /// <summary>  
        /// Gets information about the intent model  
        /// </summary>  
        /// <param name=”name”>intent name</param>  
        /// <param name=”appId”>app id</param>  
        /// <param name=”appVersionId”>app version</param>  
        /// <returns>app intent</returns>  
        public async Task<Intent> GetIntentByNameAsync(string name, string appId, string appVersionId)    
        {    
            var apps = await GetAllIntentsAsync(appId, appVersionId);    
            return apps.FirstOrDefault(intent => intent.Name.Equals(name));    
        }    

        /// <summary>  
        /// Creates a new app intent and returns the id  
        /// </summary>  
        /// <param name=”name”>intent name</param>  
        /// <param name=”appId”>app id</param>  
        /// <param name=”appVersionId”>app version</param>  
        /// <returns>The ID of the created intent</returns>  
        public async Task<stringAddIntentAsync(string name, string appId, string appVersionId)    
        {    
            var intent = new
            {    
                name = name    
            };    
            var response = await Post($“/apps/{appId}/versions/{appVersionId}/intents”, intent);    
            return JsonConvert.DeserializeObject<string>(response);    
        }    

        /// <summary>  
        /// Change the name of app intent  
        /// </summary>  
        /// <param name=”id”>intent id</param>  
        /// <param name=”name”>new intent name</param>  
        /// <param name=”appId”>app id</param>  
        /// <param name=”appVersionId”>app version</param>  
        /// <returns></returns>  
        public async Task RenameIntentAsync(string id, string name, string appId, string appVersionId)    
        {    
            var intent = new
            {    
                name = name    
            };    
            await Put($“/apps/{appId}/versions/{appVersionId}/intents/{id}”, intent);    
        }    

        /// <summary>  
        /// Deletes an intent classifier from the application  
        /// </summary>  
        /// <param name=”id”>intent id</param>  
        /// <param name=”appId”>app Id</param>  
        /// <param name=”appVersionId”>app version</param>  
        /// <returns></returns>  
        public async Task DeleteIntentAsync(string id, string appId, string appVersionId)    
        {    
            await Delete($“/apps/{appId}/versions/{appVersionId}/intents/{id}”);z    
        }    

        #endregion  

        #region Entities  

        /// <summary>  
        /// Gets information about the entity models  
        /// </summary>  
        /// <param name=”appId”>app id</param>  
        /// <param name=”appVersionId”>app version</param>  
        /// <returns>A List of app entities</returns>  
        public async Task<IReadOnlyCollection<Entity>> GetAllEntitiesAsync(string appId, string appVersionId)    
        {    
            var response = await Get($“/apps/{appId}/versions/{appVersionId}/entities”);    
            var content = await response.Content.ReadAsStringAsync();    
            if (response.IsSuccessStatusCode)    
                return JsonConvert.DeserializeObject<IReadOnlyCollection<Entity>>(content);    
            elseif (response.StatusCode != System.Net.HttpStatusCode.BadRequest)    
            {    
                var exception = JsonConvert.DeserializeObject<ServiceException>(content);    
                thrownew Exception($“{ exception.Error.Code} – { exception.Error.Message}”);    
            }    
            returnnull;    
        }    

        /// <summary>  
        /// Gets information about the entity model  
        /// </summary>  
        /// <param name=”id”>entity id</param>  
        /// <param name=”appId”>app id</param>  
        /// <param name=”appVersionId”>app version</param>  
        /// <returns>app entity</returns>  
        public async Task<Entity> GetEntityByIdAsync(string id, string appId, string appVersionId)    
        {    
            var response = await Get($“/apps/{appId}/versions/{appVersionId}/entities/{id}”);    
            var content = await response.Content.ReadAsStringAsync();    
            if (response.IsSuccessStatusCode)    
                return JsonConvert.DeserializeObject<Entity>(content);    
            elseif (response.StatusCode != System.Net.HttpStatusCode.BadRequest)    
            {    
                var exception = JsonConvert.DeserializeObject<ServiceException>(content);    
                thrownew Exception($“{ exception.Error.Code} – { exception.Error.Message}”);    
            }    
            returnnull;    
        }    

        /// <summary>  
        /// Gets information about the entity model  
        /// </summary>  
        /// <param name=”name”>entity name</param>  
        /// <param name=”appId”>app id</param>  
        /// <param name=”appVersionId”>app version</param>  
        /// <returns>app entity</returns>  
        public async Task<Entity> GetEntityByNameAsync(string name, string appId, string appVersionId)    
        {    
            var apps = await GetAllEntitiesAsync(appId, appVersionId);    
            return apps.FirstOrDefault(Entity => Entity.Name.Equals(name));    
        }    

        /// <summary>  
        /// Creates a new app entity and returns the id  
        /// </summary>  
        /// <param name=”name”>entity name</param>  
        /// <param name=”appId”>app id</param>  
        /// <param name=”appVersionId”>app version</param>  
        /// <returns>The ID of the created entity</returns>  
        public async Task<stringAddEntityAsync(string name, string appId, string appVersionId)    
        {    
            var Entity = new
            {    
                name = name    
            };    
            var response = await Post($“/apps/{appId}/versions/{appVersionId}/entities”, Entity);    
            return JsonConvert.DeserializeObject<string>(response);    
        }    

        /// <summary>  
        /// Change the name of app entity  
        /// </summary>  
        /// <param name=”id”>entity id</param>  
        /// <param name=”name”>new intent name</param>  
        /// <param name=”appId”>app id</param>  
        /// <param name=”appVersionId”>app version</param>  
        /// <returns></returns>  
        public async Task RenameEntityAsync(string id, string name, string appId, string appVersionId)    
        {    
            var entity = new
            {    
                name = name    
            };    
            await Put($“/apps/{appId}/versions/{appVersionId}/entities/{id}”, entity);    
        }    

        /// <summary>  
        /// Deletes an entity extractor from the application  
        /// </summary>  
        /// <param name=”id”>entity id</param>  
        /// <param name=”appId”>app Id</param>  
        /// <param name=”appVersionId”>app version</param>  
        /// <returns></returns>  
        public async Task DeleteEntityAsync(string id, string appId, string appVersionId)    
        {    
            await Delete($“/apps/{appId}/versions/{appVersionId}/entities/{id}”);    
        }    

        #endregion  

        #region examples  

        /// <summary>  
        /// Adds a labeled example to the application  
        /// </summary>  
        /// <param name=”appId”>app id</param>  
        /// <param name=”appVersionId”>app version</param>  
        /// <param name=”model”>object containing the example label</param>  
        /// <returns>A object of utterance created</returns>  
        public async Task<Utterance> AddExampleAsync(string appId, string appVersionId, Example model)    
        {    
            var response = await Post($“/apps/{appId}/versions/{appVersionId}/example”, model);    
            return JsonConvert.DeserializeObject<Utterance>(response);    
        }    

        #endregion  

        #region Train  

        /// <summary>  
        /// Sends a training request for a version of a specified LUIS app  
        /// </summary>  
        /// <param name=”appId”>app id</param>  
        /// <param name=”appVersionId”>app version</param>  
        /// <returns>A object of training request details</returns>  
        public async Task<TrainingDetails> TrainAsync(string appId, string appVersionId)    
        {    
            var response = await Post($“/apps/{appId}/versions/{appVersionId}/train”);    
            return JsonConvert.DeserializeObject<TrainingDetails>(response);    
        }    

        /// <summary>  
        /// Gets the training status of all models (intents and entities) for the specified LUIS app  
        /// </summary>  
        /// <param name=”appId”>app id</param>  
        /// <param name=”appVersionId”>app version</param>  
        /// <returns>A list of trainings status</returns>  
        public async Task<IEnumerable<Training>> GetTrainingStatusListAsync(string appId, string appVersionId)    
        {    
            var response = await Get($“/apps/{appId}/versions/{appVersionId}/train”);    
            var content = await response.Content.ReadAsStringAsync();    
            if (response.IsSuccessStatusCode)    
                return JsonConvert.DeserializeObject<IEnumerable<Training>>(content);    
            else
            {    
                var exception = JsonConvert.DeserializeObject<ServiceException>(content);    
                thrownew Exception($“{ exception.Error.Code} – { exception.Error.Message}”);    
            }    
        }    

        #endregion  

        #region Publish  

        /// <summary>  
        /// Publishes a specific version of the application  
        /// </summary>  
        /// <param name=”appId”>app id</param>  
        /// <param name=”appVersionId”>app version</param>  
        /// <param name=”isStaging”></param>  
        /// <param name=”region”>If the app is created in “westeurope”, then the publish location is also “westeurope.” For all other app locations, the publish location is “westus”</param>  
        /// <returns>A object of publish details</returns>  
        public async Task<Publish> PublishAsync(string appId, string appVersionId, bool isStaging, string region)    
        {    
            var model = new
            {    
                versionId = appVersionId,    
                isStaging = isStaging.ToString(),    
                region = region    
            };    
            var response = await Post($“/apps/{appId}/publish”, model);    
            return JsonConvert.DeserializeObject<Publish>(response);    
        }    

        #endregion  
    }    
}