Azure ad b2c custom connector "ShowBlockPage" response is not working - azure-ad-b2c

I am following the documentation here to return the blocking response https://learn.microsoft.com/en-us/azure/active-directory-b2c/add-api-connector?pivots=b2c-user-flow#example-of-a-blocking-response from api connector to azure ad b2c, however even after constructing the right response as shown in the documentation, I am still not able to show the blocking page for b2c user flow.
Note that this connector gets invoked at sign-in.
I have verified that the response from api which seems correct and looks like below
{
"version": "1.0.0",
"action": "ShowBlockPage",
"userMessage": "You must have a local account registered for Contoso."
}
With this, was hoping to see a blocking page as below (screenshot from docs) but b2c does not show it and goes straight to the connected application.
What did I miss? any pointers would be appreciated. TIA.
Here is my api connector's code
public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
// Get the request body
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
// If input data is null, show block page
if (data == null)
{
return (ActionResult)new OkObjectResult(new ResponseContent("ShowBlockPage", "There was a problem with your request."));
}
// Print out the request body
log.LogInformation("Request body: " + requestBody);
// check for issuer
if(data.identities != null)
{
string issuer = data.identities[0].issuer;
log.LogInformation("issuer detected: " + issuer);
if(issuer == "github.com")
{
log.LogInformation("Returning an error!");
//return (ActionResult)new BadRequestObjectResult(new ResponseContent("ValidationError", "Please provide a Display Name with at least five characters."));
return (ActionResult)new OkObjectResult(new ResponseContent("ShowBlockPage", "You must have a local account registered for Contoso."));
}
}
// Validation passed successfully, return `Allow` response.
return (ActionResult)new OkObjectResult(new ResponseContent()
{
jobTitle = "This value return by the API Connector"//,
// You can also return custom claims using extension properties.
//extension_CustomClaim = "my custom claim response"
});
}
and here is the ResponseContent class
public class ResponseContent
{
public const string ApiVersion = "1.0.0";
public ResponseContent()
{
this.version = ResponseContent.ApiVersion;
this.action = "Continue";
}
public ResponseContent(string action, string userMessage)
{
this.version = ResponseContent.ApiVersion;
this.action = action;
this.userMessage = userMessage;
if (action == "ValidationError")
{
this.status = "400";
}
}
public string version { get; }
public string action { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string userMessage { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string status { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string jobTitle { get; set; }
}

We ended up creating Microsoft support ticket for this and got response that this is by design. ShowBlockPage response works only with sign-up user flows and not with sign-in user flows.

Related

User Flow - API connector cannot parse response

I have an Azure B2C user flow. It is associated with an API Connector pointing to an Azure Function. The function returns a ResponseContent with extension claims:
public class ResponseContent
{
public const string ApiVersion = "1.0.0";
public ResponseContent()
{
this.version = ResponseContent.ApiVersion;
this.action = "Continue";
}
public ResponseContent(string action, string userMessage)
{
this.version = ResponseContent.ApiVersion;
this.action = action;
this.userMessage = userMessage;
}
public ResponseContent(string userTypes, string accountIdentifiers, string pricebookAuthorized, string portalAuthorized)
{
this.version = ResponseContent.ApiVersion;
this.action = "Continue";
this.extension_UserTypes = userTypes;
this.extension_AccountIdentifiers = accountIdentifiers;
this.extension_PricebookAuthorized = pricebookAuthorized;
this.extension_PortalAuthorized = portalAuthorized;
}
public string version { get; }
public string action { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string userMessage { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string extension_UserTypes { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string extension_AccountIdentifiers { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string extension_PricebookAuthorized { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string extension_PortalAuthorized { get; set; }
}
Here are the claims of the user flow:
When I run this Azure function using Postman, the following is returned:
{
"version": "1.0.0",
"action": "Continue",
"extension_UserTypes": "",
"extension_AccountIdentifiers": "",
"extension_PricebookAuthorized": "",
"extension_PortalAuthorized": ""
}
But when I try to run the user flow on Azure, I get
Microsoft.Identity.Client.MsalServiceException:
AADB2C90261: The claims exchange 'PreSendClaimsRestful' specified in
step '2' returned HTTP error response that could not be parsed.
What might be wrong, and how this can be diagnosed?
Please check if below points can help:
Each key value pair in the JSON is treated as string, string
collection or Boolean.
AADB2C may not deserialise the claim in the JSON you send. One may
need to deserialise the string at the API, or will have to return a
nested JSON object without the escape characters.
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
Reference: dotnet-external-identities-api-connector-azure-function-validate
ยท GitHub
To troubleshoot the unexpected response, try sending Azure AD B2C
logs to Application Insights.
References:
Azure B2C - REST API call Error
Add extra claims to an Azure B2C user flow using API connectors and
ASP.NET Core | (damienbod.com)
how-to-parse-json-in-net-core

Xamarin forms push notification using azure

I have developed an app with Xamarin Forms and implemented push notification using Azure Notification Hub.
I followed this tutorial from Microsoft site :
https://learn.microsoft.com/en-us/azure/notification-hubs/notification-hubs-backend-service-xamarin-forms
I receive the notification when send it to all ,The problem is when I use the 'Tag' in order to send it to specific user(I register this user with certain tag when he log in the application.)
This is not working and I don't even have an idea how to check where is the problem.
I tried to check out weather the tag is not assigned correctly or not assigned at all but it's not possible to check it.
What should I do?
How can I see all the tags I have in system and who is registered to the tag?
Maybe I didn't understood it correctly but I don't create the Tag before the user register ,I just add it to the Tags List when the user is registered to the system.
public class DeviceInstallation
{
[Required]
public string InstallationId { get; set; }
[Required]
public string Platform { get; set; }
[Required]
public string PushChannel { get; set; }
public IList<string> Tags { get; set; } = Array.Empty<string>(); //Generate tag when register device and add it to list
}
public async Task RegisterDeviceAsync(params string[] tags)
{
var deviceInstallation = DeviceInstallationService?.GetDeviceInstallation(tags);
if (deviceInstallation == null)
throw new Exception($"Unable to get device installation information.");
if (string.IsNullOrWhiteSpace(deviceInstallation.InstallationId))
throw new Exception($"No {nameof(deviceInstallation.InstallationId)} value for {nameof(DeviceInstallation)}");
if (string.IsNullOrWhiteSpace(deviceInstallation.Platform))
throw new Exception($"No {nameof(deviceInstallation.Platform)} value for {nameof(DeviceInstallation)}");
if (string.IsNullOrWhiteSpace(deviceInstallation.PushChannel))
throw new Exception($"No {nameof(deviceInstallation.PushChannel)} value for {nameof(DeviceInstallation)}");
await SendAsync<DeviceInstallation>(HttpMethod.Put, RequestUrl, deviceInstallation)
.ConfigureAwait(false);
var serializedTags = JsonConvert.SerializeObject(tags);
await SecureStorage.SetAsync(CachedTagsKey, serializedTags);
}
The following code is in the server:
public async Task<bool> CreateOrUpdateInstallationAsync(DeviceInstallation deviceInstallation, CancellationToken token)
{
if (string.IsNullOrWhiteSpace(deviceInstallation?.InstallationId) ||
string.IsNullOrWhiteSpace(deviceInstallation?.Platform) ||
string.IsNullOrWhiteSpace(deviceInstallation?.PushChannel))
return false;
var installation = new Installation()
{
InstallationId = deviceInstallation.InstallationId,
PushChannel = deviceInstallation.PushChannel,
Tags = deviceInstallation.Tags
};
if (_installationPlatform.TryGetValue(deviceInstallation.Platform, out var platform))
installation.Platform = platform;
else
return false;
try
{
await _hub.CreateOrUpdateInstallationAsync(installation, token);
}
catch
{
return false;
}
return true;
}

AutoQuery is not getting the name db connection when run through gateway

I have an implementation, where I am calling an autoquery operation via the service gateway. The service gateway will successfully call both internal and external operations. However, any autoquery operation fails because it is not getting the connection string set. These same autoquery operations work just fine when called directly and not through the gateway.
Here is the stack trace.
at ServiceStack.OrmLite.OrmLiteConnectionFactory.CreateDbConnection() in C:\\BuildAgent\\work\\27e4cc16641be8c0\\src\\ServiceStack.OrmLite\\OrmLiteConnectionFactory.cs:line 70\r\n at ServiceStack.OrmLite.OrmLiteConnectionFactory.OpenDbConnection() in C:\\BuildAgent\\work\\27e4cc16641be8c0\\src\\ServiceStack.OrmLite\\OrmLiteConnectionFactory.cs:line 95\r\n at ServiceStack.ServiceStackHost.GetDbConnection(IRequest req) in C:\\BuildAgent\\work\\3481147c480f4a2f\\src\\ServiceStack\\ServiceStackHost.Runtime.cs:line 691\r\n at ServiceStack.AutoQuery.GetDb(Type type, IRequest req) in C:\\BuildAgent\\work\\3481147c480f4a2f\\src\\ServiceStack.Server\\AutoQueryFeature.cs:line 598\r\n at ServiceStack.AutoQuery.CreateQuery[From](IQueryDb`1 dto, Dictionary`2 dynamicParams, IRequest req) in C:\\BuildAgent\\work\\3481147c480f4a2f\\src\\ServiceStack.Server\\AutoQueryFeature.cs:line 608\r\n at IDOE.SecurityPortal.Api.ServiceInterface.OrganizationUserStaffTypeService.Get(QueryOrganizationUserStaffTypes query) in E:\\source\\repos\\Azure - Security Portal\\src\\IDOE.SecurityPortal\\IDOE.SecurityPortal.Api.ServiceInterface\\OrganizationUserStaffTypeService.cs:line 47\r\n at ServiceStack.Host.ServiceRunner`1.<ExecuteAsync>d__15.MoveNext() in C:\\BuildAgent\\work\\3481147c480f4a2f\\src\\ServiceStack\\Host\\ServiceRunner.cs:line 133
Database Connection Registration in startup.cs
var dbFacotry = container.Resolve<IDbConnectionFactory>();
dbFacotry.RegisterConnection("SecPortal", AppSettings.Get<string>("SQLSERVER-SECPORTAL-CONNECTIONSTRING"), SqlServer2017Dialect.Provider);
dbFacotry.RegisterConnection("EdfiMdm", AppSettings.Get<string>("SQLSERVER-EDFIMDM-CONNECTIONSTRING"), SqlServer2017Dialect.Provider);
Plugins.Add(new AutoQueryFeature { IncludeTotal = true });
AutoQuery Definition
[Authenticate]
[RequiredClaim("scope", "secprtl-read")]
[Route("/files", Verbs = "GET")]
[ConnectionInfo(NamedConnection = "SecPortal")]
public class QueryFiles : QueryDb<Types.File>
{
[QueryDbField(Field = "Id", Template = "({Value} IS NULL OR {Field} = {Value})")]
public int? Id { get; set; }
[QueryDbField(Field = "FileName", Template = "({Value} IS NULL OR UPPER({Field}) LIKE UPPER({Value}))", ValueFormat = "%{0}%")]
public string FileName { get; set; }
[QueryDbField(Field = "UserId", Template = "({Value} IS NULL OR UPPER({Field}) LIKE UPPER({Value}))", ValueFormat = "%{0}%")]
public string UserId { get; set; }
[QueryDbField(Field = "StateOrganizationId", Template = "({Value} IS NULL OR UPPER({Field}) LIKE UPPER({Value}))", ValueFormat = "%{0}%")]
public string StateOrganizationId { get; set; }
[QueryDbField(Field = "Notes", Template = "({Value} IS NULL OR UPPER({Field}) LIKE UPPER({Value}))", ValueFormat = "%{0}%")]
public string Notes { get; set; }
}
Code calling the service
public class ContactService : Service
{
public ContactService()
{
}
public async Task<object> Post(PostContact request)
{
try
{
var files = base.Gateway.Send(new QueryFiles() { });
return new Contact() { Name = request.Name };
}
catch (Exception ex)
{
throw ex;
}
}
}
Custom Service Gateway
public class CustomServiceGatewayFactory : ServiceGatewayFactoryBase
{
private IRequest request;
public override IServiceGateway GetServiceGateway(IRequest request)
{
this.request = request;
return base.GetServiceGateway(request);
}
public override IServiceGateway GetGateway(Type requestType)
{
var isLocal = HostContext.Metadata.RequestTypes.Contains(requestType);
if (isLocal)
{
return base.localGateway;
}
else
{
return new JsonServiceClient("https://localhost:6001")
{
BearerToken = request.GetBearerToken()
};
}
}
}
Custom service gateway registration in startup.cs
container.Register<IServiceGatewayFactory>(x => new CustomServiceGatewayFactory()).ReusedWithin(ReuseScope.None);
The call being made in the service class is a local call. Calling an external service that uses autoquery works just fine. I can also call the local service directly with no problem.
I created a custom autoquery method in the service interface, I noticed that the db connection info was not populated on the request.items array. So I manually added that information to the request, and it worked as expected. So somehow, in my setup, the autoquery operations that are called locally, the db connection info is not getting added to the request object.
Request Filter Attributes like [ConnectionInfo] is only applied on HTTP Requests, not internal Service Gateway requests.
The Connection info isn't configured because it's not annotated on your PostContact Service Request DTO that calls the in-procces Service Gateway.
You can have the [ConnectionInfo] on the QueryFiles AutoQuery Request DTO attached to the current Request with:
public async Task<object> Post(PostContact request)
{
try
{
typeof(QueryFiles).FirstAttribute<ConnectionInfoAttribute>()
.Execute(Request,Response,request);
var files = base.Gateway.Send(new QueryFiles() { });
return new Contact() { Name = request.Name };
}
catch (Exception ex)
{
throw ex;
}
}

Azure function to create Service Principal [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
What's the recommended way to create Azure function to create a AAD Service principal.
Should we be doing Azure function using Powershell maybe?
As per your comment To Create User From Azure function using client_credentials grant flow Here I am giving you exact sample for azure function. Just plug and play :))
Example Contains:
How Would you get token using client_credentials flow
Create User on Azure Active Directory tenant Azure Function
Access Token Class:
public class AccessTokenClass
{
public string token_type { get; set; }
public string expires_in { get; set; }
public string resource { get; set; }
public string scope { get; set; }
public string access_token { get; set; }
}
Azure Active Directory Create User Class:
public class AzureFunctionCreateUserClass
{
public bool accountEnabled { get; set; }
public string displayName { get; set; }
public string mailNickname { get; set; }
public string userPrincipalName { get; set; }
public PasswordProfile passwordProfile { get; set; }
}
Azure Active Directory User Password Profile Class:
public class PasswordProfile
{
public bool forceChangePasswordNextSignIn { get; set; }
public string password { get; set; }
}
Reference To Add:
using System;
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 System.Net.Http;
using System.Collections.Generic;
using System.Net.Http.Headers;
Azure Function Body:
[FunctionName("FunctionCreateUserUsingRestAPI")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
try
{
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
AzureFunctionCreateUserClass objFuncRequestClass = JsonConvert.DeserializeObject<AzureFunctionCreateUserClass>(content);
// Variable For Validation message return
dynamic validationMessage;
// Validate param I am checking here. For Testing I am not taking from here But you can
if (string.IsNullOrEmpty(objFuncRequestClass.displayName))
{
validationMessage = new OkObjectResult("displayName is required!");
return (IActionResult)validationMessage;
}
if (string.IsNullOrEmpty(objFuncRequestClass.mailNickname))
{
validationMessage = new OkObjectResult("mailNicknameis required!");
return (IActionResult)validationMessage;
}
if (string.IsNullOrEmpty(objFuncRequestClass.userPrincipalName))
{
validationMessage = new OkObjectResult("userPrincipalName is required Format: UserName#YourTenant.onmicrosoft.com!");
return (IActionResult)validationMessage;
}
//Token Request Endpoint
string tokenUrl = $"https://login.microsoftonline.com/YourTenant.onmicrosoft.com/oauth2/token";
var tokenRequest = new HttpRequestMessage(HttpMethod.Post, tokenUrl);
tokenRequest.Content = new FormUrlEncodedContent(new Dictionary<string, string>
{
["grant_type"] = "client_credentials",
["client_id"] = "b603c7be-a866-Your_client_id-e6921e61f925",
["client_secret"] = "Vxf1SluKbgu4PF0N-client_Secret-SeZ8wL/Yp8ns4sc=",
["resource"] = "https://graph.microsoft.com"
});
dynamic json;
AccessTokenClass results = new AccessTokenClass();
HttpClient client = new HttpClient();
//Request For Token
var tokenResponse = await client.SendAsync(tokenRequest);
json = await tokenResponse.Content.ReadAsStringAsync();
//Extract Token Into class
results = JsonConvert.DeserializeObject<AccessTokenClass>(json);
var accessToken = results.access_token;
//Azure Ad Password profile object
PasswordProfile objPass = new PasswordProfile();
objPass.forceChangePasswordNextSignIn = true;
objPass.password = "yourNewUserPass";
//Azure AD user Object
AzureFunctionCreateUserClass objCreateUser = new AzureFunctionCreateUserClass();
objCreateUser.accountEnabled = true;
objCreateUser.displayName = "KironFromFucntion";
objCreateUser.mailNickname = "KironMailFromFunction";
objCreateUser.userPrincipalName = "UserName#YourTenant.onmicrosoft.com";
objCreateUser.passwordProfile = objPass;
//Convert class object to JSON
var jsonObj = JsonConvert.SerializeObject(objCreateUser);
var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json");
using (HttpClient clientNew = new HttpClient())
{
var postJsonContent = new StringContent(jsonObj, Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//Post Rquest To Create User Rest Endpoint URL: https://graph.microsoft.com/v1.0/users
var rsponseFromApi= await client.PostAsync("https://graph.microsoft.com/v1.0/users", postJsonContent);
//Check Reqeust Is Successfull
if (rsponseFromApi.IsSuccessStatusCode)
{
var result_string = await responseFromApi.Content.ReadAsStringAsync();
dynamic responseResults = JsonConvert.DeserializeObject<dynamic>(result_string);
return new OkObjectResult(responseResults);
}
else
{
var result_string = await rsponseFromApi.Content.ReadAsStringAsync();
return new OkObjectResult(result_string);
}
}
}
catch (Exception ex)
{
return new OkObjectResult(ex.Message);
}
}
Request Format:
{
"accountEnabled": true,
"displayName": "displayName-value",
"mailNickname": "mailNickname-value",
"userPrincipalName": "upn-value#tenant-value.onmicrosoft.com",
"passwordProfile" : {
"forceChangePasswordNextSignIn": true,
"password": "password-value"
}
}
Check Newly Created User On Azure Portal:
Just to sure check your newly created user on Azure Portal All Users. See the screen shot below:
Point To Remember:
For Azure Active Directory Create users access make sure you have following permission:
User.ReadWrite.All
Permission Type: Application
You can check here. See the screen shot for better understanding: make sure you have clicked Grant admin consent for yourTenant after adding permission.
Note: This is how you can Create User on Azure Active Directory using Azure Function with Client_Credentials token flow token to a specific API endpoint efficiently.

Microsoft bot with Direct line Rest API for newbie of BOT

I am a newbie of Microsoft bot.
My company have their own communication application, and i wanna connect my bot with communication application, my client can use my bot on my campany's communication application. I read about it need to use Direct Line to do it. But i really don't know how to do it.
Does anybody help me ?or give me some suggestions? or any example of that.
Thank you so much.
Please refer documentation about direct line approach for Bot framework.
What you have to do is use https://directline.botframework.com/api/conversations as your endpoint and call those API as shown in the documentation.
Example :- I just tried with ASP.MVC application. I created a text box and button for submit message to bot.
First enable direct link in your bot application. Then remember that secret.
Following code sample shows you how to connect your chat app or your company app with bot you built using bot frame work.
First you need to authorize your access to direct link API.
client = new HttpClient();
client.BaseAddress = new Uri("https://directline.botframework.com/api/conversations/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("BotConnector", "[Your Secret Key Here]");
response = await client.GetAsync("/api/tokens/");
if (response.IsSuccessStatusCode)
If you are success with previous response you can start a new Conversation
Model -
public class Conversation
{
public string conversationId { get; set; }
public string token { get; set; }
public string eTag { get; set; }
}
Code inside controller -
var conversation = new Conversation();
response = await client.PostAsJsonAsync("/api/conversations/",conversation);
if (response.IsSuccessStatusCode)
If you success with this response you will get conversationId and a token to start messaging.
Then pass your message to bot via following code,
Conversation ConversationInfo = response.Content.ReadAsAsync(typeof(Conversation)).Result as Conversation;
string conversationUrl = ConversationInfo.conversationId+"/messages/";
Message msg = new Message() { text = message };
response = await client.PostAsJsonAsync(conversationUrl,msg);
if (response.IsSuccessStatusCode)
If you get a success response, that means you have already sent your message to the bot. Now you need to get the reply message from BOT
To get the message from bot,
response = await client.GetAsync(conversationUrl);
if (response.IsSuccessStatusCode){
MessageSet BotMessage = response.Content.ReadAsAsync(typeof(MessageSet)).Result as MessageSet;
ViewBag.Messages = BotMessage;
IsReplyReceived = true;
}
Here you get a Message set, That means the message you sent and the reply from the Bot. You can now display it in your chat window.
Message Model -
public class MessageSet
{
public Message[] messages { get; set; }
public string watermark { get; set; }
public string eTag { get; set; }
}
public class Message
{
public string id { get; set; }
public string conversationId { get; set; }
public DateTime created { get; set; }
public string from { get; set; }
public string text { get; set; }
public string channelData { get; set; }
public string[] images { get; set; }
public Attachment[] attachments { get; set; }
public string eTag { get; set; }
}
public class Attachment
{
public string url { get; set; }
public string contentType { get; set; }
}
Using those API calls you can easily connect any of your custom chat applications with bot framework. Below is the full code inside one method for you to get idea about how you can archive your goal.
private async Task<bool> PostMessage(string message)
{
bool IsReplyReceived = false;
client = new HttpClient();
client.BaseAddress = new Uri("https://directline.botframework.com/api/conversations/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("BotConnector", "[Your Secret Code Here]");
response = await client.GetAsync("/api/tokens/");
if (response.IsSuccessStatusCode)
{
var conversation = new Conversation();
response = await client.PostAsJsonAsync("/api/conversations/", conversation);
if (response.IsSuccessStatusCode)
{
Conversation ConversationInfo = response.Content.ReadAsAsync(typeof(Conversation)).Result as Conversation;
string conversationUrl = ConversationInfo.conversationId+"/messages/";
Message msg = new Message() { text = message };
response = await client.PostAsJsonAsync(conversationUrl,msg);
if (response.IsSuccessStatusCode)
{
response = await client.GetAsync(conversationUrl);
if (response.IsSuccessStatusCode)
{
MessageSet BotMessage = response.Content.ReadAsAsync(typeof(MessageSet)).Result as MessageSet;
ViewBag.Messages = BotMessage;
IsReplyReceived = true;
}
}
}
}
return IsReplyReceived;
}
Thanks Cheers with you bot.

Resources