How can I directly call the service method in index.js - c#

I would like to know if I can call the service method in index.js directly. Instead of going thru index.razor page. Because the content I am transferring from index.razor to index.js is huge in size (high MBs) and takes a long time to go between these pages. I would rather like to skip index.razor and directly call service method in index.js. Sample code below:
FileRepository:
public async Task<Block> GetFile(string fileName)
{
....
res.Byte = data;
return res;
}
FileService:
public async Task<Block> GetFile(string fileName)
{
var response = await_httpClient.GetAsync($"api/data/{fileName}");
var result = await response.Content.ReadFromJsonAsync<Block>();
return result
}
Passing the result contentStr to index.js
Index.razor:
private Block result;
private async Task open(string fileName)
{
contentStr = "";
do
{
result = await FileService.GetFile(fileName);
contentStr = contentStr + System.Text.Encoding.Default.GetString(result.Byte);
await JSRuntime.InvokeVoidAsync("Chart", contentStr); // calls `chart `method in index.js
} while (contentLength == something);
}
I would like to directly call FileService.GetFile below in index.js, instead of contentStr is being transferred from index.razor.
Index.js:
window.Chart = (contentStr) => {
var data = contentStr
}
Edited:
public class Block
{
public byte[] Byte { get; set; }
public long contentLength { get; set; }
}

Following this document and I had code below in my .razor component.
By the way, document mentioned The .NET method must be public, static, and have the [JSInvokable] attribute.
#inject IJSRuntime JS
<div>Current Content: #currentContent</div>
<button class="btn btn-primary" #onclick="addAppend">Click me</button>
#code {
private string currentContent = "hello";
private async Task addAppend()
{
currentContent = await JS.InvokeAsync<string>("changeText", currentContent);
await JS.InvokeVoidAsync("logContent");
}
[JSInvokable]
public static string getContent()
{
return "Hello world";
}
}
And I had this script in index.html page.
<script>
window.changeText = (strData) => {
var temp = "+ append Content";
var res = strData + temp;
return res;
};
window.logContent = () => {
DotNet.invokeMethodAsync('BlazorWsamAad', 'getContent')
.then(data => {
console.log(data);
alert(data);
});
};
</script>
And this is the test result.

Related

How do I instantiate a C# service and use its data in a Blazor component

I am using Blazor and I am a beginner.
Currently I have several Blazor components that all need the same JSON data (data fetched from one URL, e.g., http://localhost/todo)
Instead of fetching the same URL inside all my components and duplicating my code, I decided to create a Service that fetchs the URL and share this service's output accross my components.
Here is the service, and all it does fetch a URL and return a JSON object (at least that is what I am trying to do)
using TodoApp.Models.TodoTestModel;
using Newtonsoft.Json;
using System.Net.Http.Headers;
namespace Todo.Services
{
public class Todo
{
public string TodoURL { get; set; }
public object result { get; set; }
async public Task<object> TodoTypes()
{
using (HttpClient client = new HttpClient())
{
// HTTP header stuff
HttpResponseMessage response = client.GetAsync(TodoURL).Result;
response.EnsureSuccessStatusCode();
string responseData = await response.Content.ReadAsStringAsync();
result = JsonConvert.DeserializeObject<TodoTestModel>(responseData);
return result;
}
}
}
}
}
The idea is call this service and give my components the output as
<TodoComponent ToDoResult="#result"> </ToDoComponent>
But I am having a problem when instanciating the object, e.g,:
#page "/"
#using TodoApp.Services;
#inject TodoApp.Services.Todo Todo;
<h5> List of todos </h5>
#code {
Todo td = new Todo();
td.TodoURL = ".." // does not work
}
In short I am trying to do the following:
Instanciate the class
Provide it a URL
Get the JSON data (result) to pass it into my TodoComponent
Thanks for the help
vaeon you can directly use client.GetJsonAsync and avoid the deserialization step in Vikram's example.The returned result set is not matching with the expected typeof List.
var response = await client.GetFromJsonAsync(TodoURL);
return response;
Program.cs
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using BlazorApp1;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddScoped(sp => new TodoService());
await builder.Build().RunAsync();
TodoService.cs
namespace BlazorApp1;
public class TodoService
{
public TodoService()
{
}
public List<string> GetTodos()
{
//write your code here that fetches the todos using the TodosUrl
throw new NotImplementedException();
}
public string TodosUrl { get; set; } = "https://google.com";
}
TodosComponent
#inject TodoService TodoService
<ul>
#foreach (var todo in Todos)
{
<li>#todo</li>
}
</ul>
#code {
public List<string> Todos { get; set; }
protected override void OnInitialized()
{
TodoService.TodosUrl = "https://stackoverflow.com";
Todos = TodoService.GetTodos();
base.OnInitialized();
}
}
Add below code before await builder.Build().RunAsync(); in the Program.cs file.
Program.cs:
...
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new
Uri(builder.HostEnvironment.BaseAddress) });
// Register services
builder.Services.AddScoped<TodoService>(); // <----- Add this line
await builder.Build().RunAsync();
TodoService.cs:
public class TodoService
{
public string TodoURL { get; set; }
public async Task<List<TodoTestModel>> GetTodoTypesAsync()
{
using (HttpClient client = new HttpClient())
{
// HTTP header stuff
HttpResponseMessage response = await client.GetAsync(TodoURL);
response.EnsureSuccessStatusCode();
string responseData = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<List<TodoTestModel>>(responseData);
}
}
}
In TodoComponent.razor file, add the below code:
#page "/"
#using TodoApp.Services;
#inject TodoService TodoService;
<h5> List of todos </h5>
#if(todoList is not null && todoList.Any())
{
<ul>
#foreach(var item in todoList)
{
<li>#item.Name</li>
}
</ul>
}
#code {
private List<TodoTestModel> todoList;
protected override async Task OnInitializedAsync()
{
TodoServices.TodoURL = ""; // TODO: set the API url
todoList = await TodoService.GetTodoTypesAsync();
await base.OnInitializedAsync();
}
}

onpaste input event in blazor and typescript

The #onpaste is a blazor DOM event executed when content is pasted in an input.
now, I want to get this text content from typescript (blazor doesn't support it).
razor:
#inject IJSRuntime _Js
<input class="otp-input"
#ref="myInputRef"
#onpaste="HandleOnPaste" />
#code {
private ElementReference myInputRef { get; set; }
private async Task HandleOnPaste()
{
var pastedData = await _js.InvokeAsync<string?>("OtpInput.getPastedData")
// DO Something
}
}
ts:
class OtpInput {
static getPastedData(e: ClipboardEvent) {
let pastedData = e.clipboardData!.getData('text');
return pastedData;
}
}
this does not work and return error: TypeError: Cannot read properties of undefined (reading 'clipboardData')
You can use a different approach. Add event listener to the input element using javascript then call dotnet method and pass the event data. I use javascript but you can modify accordingly for typescript.
pasteInteropHelper.js:
export function addOnPasteEventListener(elem, componentInstance) {
elem.onpaste = (e) => {
var text = e.clipboardData.getData('text');
componentInstance.invokeMethod('HandlePaste', text);
}
}
razor component:
#inject IJSRuntime JS
<input #ref="_inputRef" />
#code {
private ElementReference _inputRef;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
var module = await JS.InvokeAsync<IJSObjectReference>(
"import", "./pasteInteropHelper.js");
var selfReference = DotNetObjectReference.Create(this);
await module.InvokeVoidAsync("addOnPasteEventListener", _inputRef, selfReference);
}
}
[JSInvokable]
public void HandlePaste(string text)
{
Console.WriteLine(text);
}
}

ChatMessages.Add(message) is not hit

I'm getting started with simple signalR application. When user puts his "name" and "room". It is sent to my hub
//This is Index page
public async Task<ActionResult> OnPost()
{
UserConnection userConnection = new()
{
Name = UserInput,
Room = JoinRoomInput
};
await _hubConnection.SendAsync("JoinRoom", userConnection);
return RedirectToPage("ChatGroup");
}
my chat looks like this
public class ChatHub : Hub<IChatClient>
{
private readonly string _botUser;
public ChatHub()
{
_botUser = "MyChat Bot";
}
public async Task JoinRoom(UserConnection userConnection)
{
await Groups.AddToGroupAsync(Context.ConnectionId, userConnection.Room);
await Clients.Group(userConnection.Room).ReceiveMessage(_botUser, $"{userConnection.Name} has joined {userConnection.Room}");
}
public async Task SendMessage(UserConnection userConnection, string message)
{
await Clients.Group(userConnection.Room).ReceiveMessage($"{userConnection.Name} : ", message);
}
}
So then, the use posts his details and hit joinroom. He is redirected to another razor page called Chatgroup.In this page, He should get the message as defined in "JoinRoom" in ChatHub.
//This is Chatgroup page
private readonly HubConnection _hubConnection;
public List<string> ChatMessages { get; set; }
public ChatGroupModel(HubConnection hubConnection)
{
_hubConnection = hubConnection;
}
public void OnGet()
{
_hubConnection.On<string>("ReceiveMessage", (message) => //Breakpoint hits here
{
ChatMessages.Add(message); // When placed a breakpoint here, It is skipped.
});
}
I'm getting ChatMessages is Null error.
So my question is how will my client side code _hubConnection.On<> get the response from chathub?
I think this is the issue.
I've registered my signalr in startup class like this
services.AddTransient<HubConnection>((ChatClient) => {
var hubConnection = new HubConnectionBuilder().WithUrl("https://localhost:44389/chathub").Build();
hubConnection.Closed += async (error) =>
{
await Task.Delay(new Random().Next(0, 5) * 1000);
await hubConnection.StartAsync();
};
hubConnection.StartAsync();
return hubConnection;
});
I get a null exception error in my razor page. I think it's because _hubConnection.On<>... skips chatmessage.add.
#foreach(var messages in Model.ChatMessages) //ChatMessages is Null
{
<div>
#messages
</div>
}

Having an Issue when I use the function for a second time with Blazor Server side and Twilio

I have made a website with Blazor Server side. I am using Twilio Voice Api to enable the user to make an emergency call. I have been able to make the call successfully. When I leave the page and then go back to the page to make the call again I am receiving this error:
Error: Microsoft.JSInterop.JSException: Cannot read property 'setToken' of undefined
TypeError: Cannot read property 'setToken' of undefined
at a.register (https://media.twiliocdn.com/sdk/js/client/v1.3/twilio.min.js:39:420)
at Function.setup (https://media.twiliocdn.com/sdk/js/client/v1.3/twilio.min.js:47:126)
at Object.setup (https://localhost:44320/js/tw.js:6:23)
at https://localhost:44320/_framework/blazor.server.js:8:31619
at new Promise (<anonymous>)
at e.beginInvokeJSFromDotNet (https://localhost:44320/_framework/blazor.server.js:8:31587)
at https://localhost:44320/_framework/blazor.server.js:1:20052
at Array.forEach (<anonymous>)
at e.invokeClientMethod (https://localhost:44320/_framework/blazor.server.js:1:20022)
at e.processIncomingData (https://localhost:44320/_framework/blazor.server.js:1:18006)
at Microsoft.JSInterop.JSRuntime.InvokeWithDefaultCancellation[T](String identifier, Object[] args)
at Microsoft.JSInterop.JSRuntimeExtensions.InvokeVoidAsync(IJSRuntime jsRuntime, String identifier, Object[] args)
at QUBeMyGuest.Pages.GuestArrivals.EmergencyContact.OnAfterRenderAsync(Boolean firstRender) in C:Pages\GuestArrivals\EmergencyContact.razor:line 75
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)
My api is
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Twilio.Jwt;
using Twilio.Jwt.AccessToken;
using Twilio.Jwt.Client;
using Twilio.TwiML;
using Twilio.Types;
using System.Net.Http;
namespace api.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class TwilioBackEndController : ControllerBase
{
public readonly string AccountSid = "xxxxxx";
public readonly string AuthToken = "xxxx";
public readonly string AppSid = "xxxxx";
public readonly string PhoneNumber = "xxxxx";
[HttpGet("token")]
public async Task<IActionResult> GetToken()
{
var scopes = new HashSet<IScope>
{
new OutgoingClientScope(AppSid),
new IncomingClientScope("tester")
};
var capability = new ClientCapability(AccountSid, AuthToken, scopes: scopes);
return await Task.FromResult(Content(capability.ToJwt(), "application/jwt"));
}
[HttpPost("voice")]
public async Task<IActionResult> PostVoiceRequest([FromForm] string phone)
{
var destination = !phone.StartsWith('+') ? $"+{phone}" : phone;
var response = new VoiceResponse();
var dial = new Twilio.TwiML.Voice.Dial
{
CallerId = PhoneNumber
};
dial.Number(new PhoneNumber(destination));
response.Append(dial);
return await Task.FromResult(Content(response.ToString(), "application/xml"));
}
}
}
My emergency contact page is:
#page "/guest/emergencycall"
#using System.ComponentModel.DataAnnotations
#inject HttpClient httpClient
#using Microsoft.Extensions.DependencyInjection
#using System.Net.Http
<EditForm Model="Input" OnValidSubmit="InitiatePhoneCall">
<DataAnnotationsValidator />
<ValidationSummary />
<p>
<label for="phoneNumber">Enter Phone Number:</label>
<InputText id="phoneNumber" #bind-Value="Input.PhoneNumber"></InputText>
<button type="submit" class="btn btn-primary" disabled="#IsDialDisabled">DIAL</button>
<button type="button" id="endBtn" class="btn btn-primary" disabled="#IsEndDisabled" #onclick="EndPhoneCall">END</button>
<button type="button" id="clearBtn" class="btn btn-primary" disabled="#IsClearDisabled" #onclick="ClearPhoneNumber">CLEAR</button>
</p>
</EditForm>
<hr />
#if (Logs.Count == 0)
{
<p>No Logs available yet</p>
}
else
{
<ul>
#foreach (var log in Logs)
{
<li>#log</li>
}
</ul>
}
#code {
private string _tokenUrl = "https://4b4cd1derdsb.ngrok.io/api/twiliobackend";
private bool appSetupRun = false;
protected bool IsDialDisabled { get; set; } = false;
protected bool IsEndDisabled { get { return !IsDialDisabled; } }
protected bool IsClearDisabled { get { return string.IsNullOrEmpty(Input.PhoneNumber); } }
protected List<string> Logs { get; set; } = new List<string>();
protected InputModel Input { get; set; } = new InputModel();
[Inject]
protected IJSRuntime JSRuntime { get; set; }
[Inject]
protected IHttpClientFactory HttpClientFactory { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender && !appSetupRun)
{
var token = await GetClientToken();
await JSRuntime.InvokeVoidAsync("appFunctions.setup", token);
appSetupRun = true;
}
}
protected async Task InitiatePhoneCall()
{
IsDialDisabled = true;
await LogMessage($"Calling the number {Input.PhoneNumber}");
await JSRuntime.InvokeVoidAsync("appFunctions.placeCall", Input.PhoneNumber);
await LogMessage($"Called the number {Input.PhoneNumber}");
StateHasChanged();
}
protected async Task EndPhoneCall()
{
IsDialDisabled = false;
await LogMessage($"Ending the call to {Input.PhoneNumber}");
await JSRuntime.InvokeVoidAsync("appFunctions.endCall");
await LogMessage($"Ended the call to {Input.PhoneNumber}");
StateHasChanged();
}
protected async Task ClearPhoneNumber()
{
await LogMessage("Clearing the phone number entry");
Input.PhoneNumber = string.Empty;
await LogMessage("Cleared the phone number entry");
StateHasChanged();
}
private async Task<string> GetClientToken()
{
var uri = new Uri(_tokenUrl);
using var client = HttpClientFactory.CreateClient();
var response = await client.GetAsync(uri);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
[JSInvokable]
public async Task LogMessage(string message)
{
Logs.Add($"{DateTimeOffset.Now} - {message}");
await Task.CompletedTask;
}
public class InputModel
{
[Required]
[Phone(ErrorMessage = "Please enter your phone number in a proper format")]
public string PhoneNumber { get; set; }
}
}
and my javascript:
window.appFunctions = {
setup: function (token) {
console.log('Getting connected');
// Setup Twilio Device
Twilio.Device.setup(token);
Twilio.Device.ready(() => {
console.log('We are connected and ready to do the thing');
});
Twilio.Device.error((err) => {
console.error('This should not have been reached. We need to do something here');
console.error(err);
});
},
placeCall: function (destination) {
console.log(`Calling ${destination}`);
Twilio.Device.connect({ phone: destination });
console.log(`Successfully called ${destination}`);
},
endCall: function () {
console.log('Ending the call');
Twilio.Device.disconnectAll();
console.log('Successfully ended the call');
}
};
Any suggestions would be great
From my little experience
when Microsoft.JSInterop.JSException occur , it's often from when you call javascript
In your code please validate javascript functions which called from JSRuntime
[Inject]
protected IJSRuntime JSRuntime { get; set; }
...
await JSRuntime.InvokeVoidAsync("appFunctions.setup", token);
await JSRuntime.InvokeVoidAsync("appFunctions.placeCall", Input.PhoneNumber);
await JSRuntime.InvokeVoidAsync("appFunctions.endCall");
and becuase setToken keyword is always used for communication setup 's function name between web and api. I guess in javascript function appFunctions.setup , some object became null after you go back to the page so It can't initialize.
as you can see in
TypeError: Cannot read property 'setToken' of undefined
at a.register (https://media.twiliocdn.com/sdk/js/client/v1.3/twilio.min.js:39:420)
at Function.setup (https://media.twiliocdn.com/sdk/js/client/v1.3/twilio.min.js:47:126)
at Object.setup (https://localhost:44320/js/tw.js:6:23)
your javascript function in file tw.js(may be line 23?) is going to use some null object for set up communicate?

Calling Twilio Voice API with Blazor

I am working on a project with blazor server and I am trying to make a voice call using Twilio.
I followed the documentation online from twilio for this to the letter but getting this error:
System.Net.Http.HttpRequestException: Response status code does not indicate success: 404 (Not Found).
at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode()
at QUBeMyGuest.Pages.GuestArrivals.EmergencyContact.GetClientToken() in C:\Pages\GuestArrivals\EmergencyContact.razor:line 98
at QUBeMyGuest.Pages.GuestArrivals.EmergencyContact.OnAfterRenderAsync(Boolean firstRender) in C:\Users\\Pages\GuestArrivals\EmergencyContact.razor:line 58
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)
The documentation stated that I should open a new asp.net core api project within my solution and add this class to the controller folder:
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Twilio.Jwt;
using Twilio.Jwt.Client;
using Twilio.TwiML;
using Twilio.Types;
using System.Net.Http;
namespace api.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class TwilioBackEndController : ControllerBase
{
public readonly string AccountSid = "xxxxxxxxxx";
public readonly string AuthToken = "xxxxxxxx";
public readonly string AppSid = "xxxxxxxx";
public readonly string PhoneNumber = "xxxxxxxx";
[HttpGet("token")]
public async Task<IActionResult> GetToken()
{
var scopes = new HashSet<IScope>
{
new OutgoingClientScope(AppSid),
new IncomingClientScope("tester")
};
var capability = new ClientCapability(AccountSid, AuthToken, scopes: scopes);
return await Task.FromResult(Content(capability.ToJwt(), "application/jwt"));
}
[HttpPost("voice")]
public async Task<IActionResult> PostVoiceRequest([FromForm] string phone)
{
var destination = !phone.StartsWith('+') ? $"+{phone}" : phone;
var response = new VoiceResponse();
var dial = new Twilio.TwiML.Voice.Dial
{
CallerId = PhoneNumber
};
dial.Number(new PhoneNumber(destination));
response.Append(dial);
return await Task.FromResult(Content(response.ToString(), "application/xml"));
}
}
}
I then set up the page to make the call with my blazor project
#page "/guest/emergencycall"
#using System.ComponentModel.DataAnnotations
#inject HttpClient httpClient
#using Microsoft.Extensions.DependencyInjection
#using System.Net.Http
<EditForm Model="Input" OnValidSubmit="InitiatePhoneCall">
<DataAnnotationsValidator />
<ValidationSummary />
<p>
<label for="phoneNumber">Enter Phone Number:</label>
<InputText id="phoneNumber" #bind-Value="Input.PhoneNumber"></InputText>
<button type="submit" class="btn btn-primary" disabled="#IsDialDisabled">DIAL</button>
<button type="button" id="endBtn" class="btn btn-primary" disabled="#IsEndDisabled" #onclick="EndPhoneCall">END</button>
<button type="button" id="clearBtn" class="btn btn-primary" disabled="#IsClearDisabled" #onclick="ClearPhoneNumber">CLEAR</button>
</p>
</EditForm>
<hr />
#if (Logs.Count == 0)
{
<p>No Logs available yet</p>
}
else
{
<ul>
#foreach (var log in Logs)
{
<li>#log</li>
}
</ul>
}
#code {
private string _tokenUrl = "https://xxxxxxxxxxxxxxx";
private bool appSetupRun = false;
protected bool IsDialDisabled { get; set; } = false;
protected bool IsEndDisabled { get { return !IsDialDisabled; } }
protected bool IsClearDisabled { get { return string.IsNullOrEmpty(Input.PhoneNumber); } }
protected List<string> Logs { get; set; } = new List<string>();
protected InputModel Input { get; set; } = new InputModel();
[Inject]
protected IJSRuntime JSRuntime { get; set; }
[Inject]
protected IHttpClientFactory HttpClientFactory { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender && !appSetupRun)
{
var token = await GetClientToken();
await JSRuntime.InvokeVoidAsync("appFunctions.setup", token);
appSetupRun = true;
}
}
protected async Task InitiatePhoneCall()
{
IsDialDisabled = true;
await LogMessage($"Calling the number {Input.PhoneNumber}");
await JSRuntime.InvokeVoidAsync("appFunctions.placeCall", Input.PhoneNumber);
await LogMessage($"Called the number {Input.PhoneNumber}");
StateHasChanged();
}
protected async Task EndPhoneCall()
{
IsDialDisabled = false;
await LogMessage($"Ending the call to {Input.PhoneNumber}");
await JSRuntime.InvokeVoidAsync("appFunctions.endCall");
await LogMessage($"Ended the call to {Input.PhoneNumber}");
StateHasChanged();
}
protected async Task ClearPhoneNumber()
{
await LogMessage("Clearing the phone number entry");
Input.PhoneNumber = string.Empty;
await LogMessage("Cleared the phone number entry");
StateHasChanged();
}
private async Task<string> GetClientToken()
{
var uri = new Uri(_tokenUrl);
using var client = HttpClientFactory.CreateClient();
var response = await client.GetAsync(uri);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
[JSInvokable]
public async Task LogMessage(string message)
{
Logs.Add($"{DateTimeOffset.Now} - {message}");
await Task.CompletedTask;
}
public class InputModel
{
[Required]
[Phone(ErrorMessage = "Please enter your phone number in a proper format")]
public string PhoneNumber { get; set; }
}
}
and then added this JS function:
window.appFunctions = {
setup: function (token) {
console.log('Getting connected');
// Setup Twilio Device
Twilio.Device.setup(token);
Twilio.Device.ready(() => {
console.log('We are connected and ready to do the thing');
});
Twilio.Device.error((err) => {
console.error('This should not have been reached. We need to do something here');
console.error(err);
});
},
placeCall: function (destination) {
console.log(`Calling ${destination}`);
Twilio.Device.connect({ phone: destination });
console.log(`Successfully called ${destination}`);
},
endCall: function () {
console.log('Ending the call');
Twilio.Device.disconnectAll();
console.log('Successfully ended the call');
}
};
in my startup file I then added this, but doesn't seem to have made a difference:
services.AddHttpClient();
if (!services.Any(x => x.ServiceType == typeof(HttpClient)))
{
services.AddScoped<HttpClient>(s =>
{
var uriHelper = s.GetRequiredService<NavigationManager>();
return new HttpClient
{
BaseAddress = new Uri(uriHelper.BaseUri)
};
});
}
Any suggestions on what I could be doing wrong?
When seeing a 404, the first thing that should come to mind is an incorrect URL. Since the 404 is coming from GetClientToken in your razor file. That means your _tokenUrl is probably incorrect. Looking at your controller, your URL should look something like https://{host}/token/. It's possible that you hardcoded the link in the documentation, meanwhile, it's supposed to be based on your controller.
PS: HTTP 404 means that the requested resource cannot be found. Get familiar with other HTTP response codes too, might save you a ton of debugging.

Categories

Resources