Blazor WASM post from Client cs code to Server controller - post

I am developing a Blazor WASM application in .NET6.
In Blazor is possible to make a call from Client component
#code {
await Http.GetFromJsonAsync<Model>("/api/model/view/" + modelId);
}
that triggers a controller in the Server project
[HttpGet, Route("/api/model/view/{id:int}")]
public async Task<Model> GetModel(int modelId)
{
try { return await Task.FromResult(_IModel.GetModel(id)); }
catch { throw; }
}
But is it possible to post from a client project via cs class like following:
HttpClient httpClient = new HttpClient();
var content = new StringContent(JsonConvert.SerializeObject(authcookie_value), Encoding.UTF8, "application/json");
httpClient.BaseAddress = new(Parameters.urlstring);
var result = httpClient.PostAsync("/api/auth/refresh", content);
And the controller on the Server project to be fired:
[HttpPost, Route("/api/auth/refresh")]
public IActionResult AuthRefresh(StringContent httpContent)
{
try
{
}
catch { throw; }
}
The above example is not working because the controller is not fired when the call is thiggered.
Any ideas?

Related

How to get messages from Azure Service Bus (Queue) in View.cshtml in ASP.NET MVC web app

I have a console application with which I can get messages from Azure Service Bus (Queue).
using System;
using System.Text;
using System.Text.Json;
using Microsoft.Azure.ServiceBus;
using SampleShared.Models;
namespace SampleAppReceiver
{
class Program
{
const string connString = "<my_connection_string>";
static IQueueClient qClient;
static async Task Main(string[] args)
{
qClient = new QueueClient(connString, "<my_queue_name>");
var msgOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
{
// How many messages we can process at time
MaxConcurrentCalls = 1,
// need to wait until a message is fully processed
AutoComplete = false,
};
qClient.RegisterMessageHandler(ProcessMessageAsync, msgOptions);
Console.ReadLine();
await qClient.CloseAsync();
}
private static async Task ProcessMessageAsync(Message msg, CancellationToken token)
{
// Deserialise the msg body
var jsonBody = Encoding.UTF8.GetString(msg.Body);
var personObj = JsonSerializer.Deserialize<Person>(jsonBody);
Console.WriteLine($"Login: {personObj.Login}");
Console.WriteLine($"Message: {personObj.Message}");
// Updating the queue that the message has been processed sucsessfully
await qClient.CompleteAsync(msg.SystemProperties.LockToken);
}
private static Task ExceptionReceivedHandler(ExceptionReceivedEventArgs args)
{
Console.WriteLine($"Something went wrong, {args.Exception}");
return Task.CompletedTask;
}
}
}
How can I correctly add all the received messages to View.cshtml from controller?
Now I have a service (C# interface) with which I can send messages from View.cshtml to Azure Service Bus (queue):
// ...
public interface IAzureBusService
{
Task SendMessageAsync(Person personMessage, string queueName);
}
// ...
Controller method:
[HttpPost]
public async Task<IActionResult> Index(Person person)
{
await _busService.SendMessageAsync(person, "personqueue");
return RedirectToAction("Index");
}
Create a service Bus in Azure portal.
Create a Queue as per the below screenshot.
I followed the below steps in displaying the queue messages in a view.
You can use the console application reference in your MVC project to display queue messages in a View by calling the method of fetching the messages from queue.
You need to use the below code in the controller class.
public ActionResult Index()
{
List<QueueMsgs> queMsglist = new List<QueueMsgs>();
QueueMsgs msgs = new QueueMsgs();
queMsglist = GetMessagesFromQueue();
return View(queMsglist);
}
public void GetMessagesFromQueue()
{
ServiceBusReceiver receiver = new ServiceBusReceiver();
receiver.Listener();
}
public void Listener()
{
ServiceBusConnectionStringBuilder conStr;
QueueClient client;
try
{
conStr = new ServiceBusConnectionStringBuilder(QueueAccessKey);
client = new QueueClient(conStr, ReceiveMode.ReceiveAndDelete, RetryPolicy.Default);
var messageHandler = new MessageHandlerOptions(ListenerExceptionHandler)
{
MaxConcurrentCalls = 1,
AutoComplete = false
};
client.RegisterMessageHandler(ReceiveMessageFromQ, messageHandler);
}
catch (Exception exe)
{
Console.WriteLine("{0}", exe.Message);
Console.WriteLine("Please restart application ");
}
public async Task ReceiveMessageFromQ(Message message, CancellationToken token)
{
string result = Encoding.UTF8.GetString(message.Body);
Console.WriteLine("Message received from Queue = {0}", result);
await Task.CompletedTask;
}
public Task ListenerExceptionHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs)
{
Console.WriteLine("{0}", exceptionReceivedEventArgs.Exception);
return Task.CompletedTask;
}
#model IEnumerable<MVC.Models.QueueMsgs>
#{
ViewBag.Title = "Queue Messages";
}
#foreach (var item in Model)
{
<div>
#item.message
<hr />
</div>
}
Displaying Queue Messages in View.

Web ApI: HttpClient is not invoking my web api action

See first how i design my web api action.
[System.Web.Http.RoutePrefix("api/Appointments")]
public class AppointmentsServiceController : ApiController
{
[System.Web.Http.HttpGet, System.Web.Http.Route("UserAppointments/{email}")]
public IHttpActionResult UserAppointments(string email)
{
if (!string.IsNullOrEmpty(email))
{
AppointmentsService _appservice = new AppointmentsService();
IEnumerable<Entities.Appointments> app = _appservice.GetUserWiseAppointments(email);
if (app.Count() <= 0)
{
return NotFound();
}
else
{
return Ok(app);
}
}
else
{
return BadRequest();
}
}
}
Now this way i am calling web api action from my asp.net mvc action by HttpClient.
public async Task<ActionResult> List()
{
var fullAddress = ConfigurationManager.AppSettings["baseAddress"] + "api/Appointments/UserAppointments/" + Session["useremail"];
IEnumerable<Entities.Appointments> app = null;
try
{
using (var client = new HttpClient())
{
using (var response = client.GetAsync(fullAddress).Result)
{
if (response.IsSuccessStatusCode)
{
var customerJsonString = await response.Content.ReadAsStringAsync();
app = JsonConvert.DeserializeObject<IEnumerable<Entities.Appointments>>(customerJsonString);
}
else
{
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(response.Content.ReadAsStringAsync().Result);
//MessageBox.Show(dict["Message"]);
}
}
}
}
catch (HttpRequestException ex)
{
// catch any exception here
}
return View();
}
}
i want capture the return IEnumerable and if not data return that also i have to capture. please show me the right direction.
Where i made the mistake. thanks
Mixing async with blocking calls like .Result
var response = client.GetAsync(fullAddress).Result
And
response.Content.ReadAsStringAsync().Result
can lead to deadlocks, which is possibly why it it not hitting your API.
Refactor the code to be async all the way.
That would mean updating the using to
var response = await client.GetAsync(fullAddress)
and the reading of the content in the else statement to
await response.Content.ReadAsStringAsync()
Reference Async/Await - Best Practices in Asynchronous Programming
It looks like you are not awaiting your GetAsync call, so in the following if (response.IsSuccessStatusCode) is probably always returning false. Try calling your method like this:
using (var response = (await client.GetAsync(fullAddress)).Result)
{

ASP.NET MVC Web API : Posting a list of objects

I'm trying to post a list of objects from my winforms application to my asp.net mvc 4 website. I've tested posting one object, and it works, but does not work for the list. It returns a 500 (Internal Server Error). Here is my code:
ASP.NET MVC Web API
public class PostTraceController : ApiController
{
public HttpResponseMessage Post(List<WebTrace> list)
{
try
{
// Some code
return Request.CreateResponse(HttpStatusCode.Created);
}
catch (Exception ex)
{
HttpContext.Current.Trace.Write("exception", ex.Message);
return Request.CreateErrorResponse(HttpStatusCode.ServiceUnavailable, ex);
}
}
public HttpResponseMessage Post(WebTrace item)
{
try
{
// Some code
return Request.CreateResponse(HttpStatusCode.Created);
}
catch (Exception ex)
{
HttpContext.Current.Trace.Write("exception", ex.Message);
return Request.CreateErrorResponse(HttpStatusCode.ServiceUnavailable, ex);
}
}
}
Win forms application
public class BaseSender
{
public BaseSender()
{
Client = new HttpClient
{
BaseAddress = new Uri(#"http://localhost/mywebsite/")
};
Client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
}
public string UserCode { get; set; }
protected readonly HttpClient Client;
public HttpResponseMessage PostAsJsonAsync(string requestUri, object value)
{
var response = Client.PostAsJsonAsync(requestUri, value).Result;
response.EnsureSuccessStatusCode();
return response;
}
}
public class WebTraceSender : BaseSender
{
private const string requestUri = "api/posttrace";
public bool Post(List<ArchiveCptTrace> list)
{
try
{
var listWebTrace = new List<WebTrace>();
foreach (var item in list)
{
listWebTrace.Add(new WebTrace
{
DateStart = item.DatePreparation,
DateEnd = item.DateCloture,
UserStart = item.UserPreparation.UserName,
UserEnd = item.UserCloture.UserName,
AmountStart = item.MontantPreparation,
AmountEnd = item.MontantCloture,
TheoricAmountEnd = item.MontantTheorique,
Difference = item.Ecart,
UserCode = UserCode
});
}
var responce = PostAsJsonAsync(requestUri, listWebTrace);
return responce.IsSuccessStatusCode;
}
catch (Exception e)
{
// TODO : Trace the exception
return false;
}
}
}
EDIT :
I've found out the scenario of the error, which is having two methods in my api controller, even thought they have different signature. If I comment one method, the post work fine (item or a list). Any ideas ?
The methods may have different signatures, but Web API can't tell the difference between them without inspecting the body, which it won't do for performance reasons.
You could do two things - either create a new class which just holds a list of WebTrace objects, and put that in a different API controller, or you could map a custom route to one of your existing methods. You could do that with ActionName attribute, however, I would probably take the first approach.

web api call from code behind

i am very new to mvc web api
I have crated a web api Post method which takes an object type "Bag" and return a HTMLString the code is as shown bellow
public HtmlString PostBag(Bag bagofItem)
{
return Utility.PostBagDiscountedItem(bagofItem);
}
now from my web site i wanted to call the API method PostBag from the controller PostBag()
and i am do not know how to and appreciate if some one can show me how to do this
what i have got in my web application is as bellow.
public class HomeController : Controller
{
private Bag _bag = new Bag();
private string uri = "http://localhost:54460/";
public ActionResult PostBag()
{
// would some one show me how to POST the _bag to API Method PostBag()
return View();
}
public class Bag
{
private static List<Product> _bag { get; set; }
public List<Product> GetBag ()
{
if (_bag == null)
_bag = new List<Product>();
return _bag;
}
}
Try this:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:54460/");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(_bag);
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Success");
}
else
{
Console.WriteLine("Error with feed");
}
}

async calls using HttpClient on MVC4

I'm playing a little bit with this new technology in .net 4.5, I would like to check the code for this call and how should I control the errors or the response of my async call.
The call is working perfectly, I need full control of possible errors returned from my service.
this is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
namespace TwitterClientMVC.Controllers
{
public class Tweets
{
public Tweet[] results;
}
public class Tweet
{
[JsonProperty("from_user")]
public string UserName { get; set; }
[JsonProperty("text")]
public string TweetText { get; set; }
}
}
public async Task<ActionResult> Index()
{
Tweets model = null;
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync("http://mywebapiservice");
response.EnsureSuccessStatusCode();
model = JsonConvert.DeserializeObject<Tweets>(response.Content.ReadAsStringAsync().Result);
return View(model.results);
}
Is this the better way to do it? or I'm missing something?
Thanks
I refactor it, is this method async as well?
public async Task<ActionResult> Index()
{
Tweets model = null;
using (HttpClient httpclient = new HttpClient())
{
model = JsonConvert.DeserializeObject<Tweets>(
await httpclient.GetStringAsync("http://search.twitter.com/search.json?q=pluralsight")
);
}
return View(model.results);
}
Is this the better way to do it?
The response.EnsureSuccessStatusCode(); will throw an exception if the status code returned by your remote service is different than 2xx. So you might want to use the IsSuccessStatusCode property instead if you want to handle the error yourself:
public async Task<ActionResult> Index()
{
using (HttpClient client = new HttpClient())
{
var response = await client.GetAsync("http://mywebapiservice");
string content = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
var model = JsonConvert.DeserializeObject<Tweets>(content);
return View(model.results);
}
// an error occurred => here you could log the content returned by the remote server
return Content("An error occurred: " + content);
}
}

Resources