I'm using PutAsJsonAsync in a Blazor WA app.
I can pass objects from client to Server in a hosted app (Server is basically a Web API app)
public async Task Pause(int id)
{
var x = new PartyList
{
Psid = id
};
var c = await _client.PutAsJsonAsync($"api/party/pause", x);
}
[HttpPut("pause")]
public async Task<IActionResult> Pause(PartyList partyList)
{
await _partySingerRepository.PauseAsync(partyList.Psid);
return Ok();
}
However I'd like to pass an int instead of a full object
public async Task Pause(int id)
{
var c = await _client.PutAsJsonAsync($"api/party/pause", id);
}
[HttpPut("pause")]
public async Task<IActionResult> Pause(int id)
{
await _partySingerRepository.PauseAsync(id);
return Ok();
}
However, the server (Web API) method doesn't get hit like this, or if I make id an anonymous type either.
Is it possible to pass in a single int or do I have to create an object?
I couldn't find anything on Google about this.
Thanks
Just had this same issue myself. Not with one parameter, but with two. It didn't work, not even with an anonymous object, until I created a class to hold the values.
Related
Have a class library that makes use of a DbContext to return results from sql.
If I want to build a
Class library method that might take a few seconds. This class is injected into an asp.net core webapp in its Startup
class Util
{
public string DoStuff(string colorVal) {
string ourValue = (from a in ctx.BigTable where a.color == colorVal select a.DoneFlag).FirstOrDefault();
return ourValue;
}
}
Do I need to make this method async also if I intend to use it from code like this
Web project
Util o;
public async Task<IViewComponentResult> InvokeAsync()
{
var item = await GetMatchingColorAsync();
return View(item);
}
private Task<string> GetMatchingColorAsync()
{
string matchingColor = o.DoStuff("red");
return Task.FromResult(matchingColor);
}
Ideally yes. You could even use FirstOrDefaultAsync while you're at it (depending on what your underlying data source is):
public async Task<string> DoStuff(string colorVal) {
string ourValue = await (from a in ctx.BigTable where a.color == colorVal select a.DoneFlag).FirstOrDefaultAsync();
var someColor = await GetMatchingColorAsync();
return ourValue;
}
Microsoft has a series of articles about Asynchronous programming with async and await that are quite well written. They're worth the read.
If you absolutely can't change the calling methods, then you could just synchronously wait:
public string DoStuff(string colorVal) {
string ourValue = (from a in ctx.BigTable where a.color == colorVal select a.DoneFlag).FirstOrDefault();
var someColor = GetMatchingColorAsync().GetAwaiter().GetResult();
return ourValue;
}
Easy right? Except it blocks the thread (you lose the benefit of the asynchronous methods) and you risk deadlocking, as explained in this article: Don't Block on Async Code.
That's Badâ„¢
I'm working on school project, and I'm trying to implement asynchronous methods in my repository classes and got this error in my API for the POST-method: Argument 1: cannot convert from 'System.Threading.Tasks.Task' to Project.Models.Booking.
Can someone please help me to solve this error?
This is how my repository-method looks like:
public async Task<Booking>CreateBooking(Booking inBooking) {
Booking booking = new Booking();
booking.BookingId = ApplicationDbContext.Bookings.Count();
booking.UserName = inBooking.UserName;
booking.UserMail = inBooking.UserMail;
booking.UserMobile = inBooking.UserMobile;
booking.Available = false;
booking.StartTime = inBooking.StartTime;
booking.EndTime = inBooking.EndTime;
booking.Date = inBooking.Date;
Add(booking);
return await Task.FromResult(booking);
//return booking;
}
And this how my Post-method looks like:
[Route("api/PostBooking")]
[HttpPost]
public async Task<IHttpActionResult> PostBooking(BookingSystemServiceBookingViewModel inBooking)
{
if (!ModelState.IsValid)
{
return BadRequest("Invalid data");
}
var booking = inBooking.booking;
booking.StartTime = inBooking.startTime;
booking.EndTime = inBooking.startTime.AddMinutes(inBooking.service.Duration);
uw.Services.AddBooking(uw.Bookings.CreateBooking(booking), inBooking.service.ServiceId);
uw.Complete();
return Ok();
}
I get the error message at: uw.Services.AddBooking(uw.Bookings.CreateBooking(booking), inBooking.service.ServiceId);`
trying to implement asynchronous methods in my repository classes
The best way to make things asynchronous is not from the "outside in". That is, you don't want to start at the controller action and say "how can I make this asynchronous?". Instead, you want to start from the lowest-level API and say "this should be asynchronous" (i.e., it's I/O-based), and let asynchrony grow out from there.
If Add actually does the database insert, then that would be the first method to be made asynchronous. Then you await your AddAsync method, and the asynchrony grows from AddAsync to CreateBookingAsync:
public async Task<Booking> CreateBookingAsync(Booking inBooking) {
Booking booking = new Booking();
...
await AddAsync(booking);
return booking;
}
[Route("api/PostBooking")]
[HttpPost]
public async Task<IHttpActionResult> PostBooking(BookingSystemServiceBookingViewModel inBooking)
{
...
uw.Services.AddBooking(await uw.Bookings.CreateBookingAsync(booking), inBooking.service.ServiceId);
uw.Complete();
return Ok();
}
If, on the other hand, it is the Complete method that actually communicates with the database, then that is the one that should be made asynchronous. In this case Add is purely an in-memory operation, and Complete is the one that saves all the database updates. So, after you convert Complete to CompleteAsync, your code would look like:
public Booking CreateBooking(Booking inBooking) {
Booking booking = new Booking();
...
Add(booking);
return booking;
}
[Route("api/PostBooking")]
[HttpPost]
public async Task<IHttpActionResult> PostBooking(BookingSystemServiceBookingViewModel inBooking)
{
...
uw.Services.AddBooking(uw.Bookings.CreateBooking(booking), inBooking.service.ServiceId);
await uw.CompleteAsync();
return Ok();
}
I am making a call to a repository which wraps EF core, messing about with the contoso example
public async void PopulateFacultySL( object selectedFaculty )
{
var data = await GetUnitOfWork().Faculties.GetAllAsync();
FacultySL = new SelectList( data, "Id", "Name", selectedFaculty );
}
When refreshing the page, sometimes the dropdown list is populated, sometimes it is not. I am late on the tech (Async and await) and trying to learn, I know it is likely to be something silly somewhere and hoping an experienced eye can see what the issue is.
protected DbSet<TEntity> TypedContext => Context.Set<TEntity>();
public virtual Task<List<TEntity>> GetAllAsync()
{
return ReturnAndFilterByInstitutionAsync( TypedContext.AsQueryable() );
}
public Task<List<TEntity>> ReturnAndFilterByInstitutionAsync( IQueryable<TEntity> query )
{
return query.Where( q => q.InstitutionId == InstitutionId ).ToListAsync();
}
Please let me know if you need to see any other class info
Edit:
This is the original calling method from the page
public IActionResult OnGet()
{
PopulateFacultySL(null);
return Page();
}
This then had to change to:
public async Task<IActionResult> OnGet()
{
FacultySL = await GetFacultySL( null );
return Page();
}
to make it accept the await keyword with the revised GetFacultySL from the suggestion below
Avoid async void fire and forget methods.
Reference Async/Await - Best Practices in Asynchronous Programming
Chances are that when PopulateFacultySL is invoked there are times when it is not completing in time to be included in the response before it is sent to the client. Which is why sometimes it is populated and sometimes it is not when the page is refreshed because they are being invoked in parallel.
What you need to do is refactor the method so that it can be awaited.
public async Task PopulateFacultySL(object selectedFaculty = null) {
var data = await GetUnitOfWork().Faculties.GetAllAsync();
FacultySL = SelectList(data, "Id", "Name", selectedFaculty);
}
and await it on page load
public async Task<IActionResult> OnGetAsync() {
await PopulateFacultySL();
return Page();
}
Now the page will wait for the data to be populated before displaying the page.
Reference Introduction to Razor Pages in ASP.NET Core
Nethereum uses an Async method to get the TransactionCount of an address.
I have put the method into a async task:
public async Task<object> GetTxCount(string address)
{
return await web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(address).ConfigureAwait(false);
}
And attempting to test it with...
[TestMethod]
public async Task TestMethodAsync()
{
string address = "0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae";
EthTest.Eth et = new EthTest.Eth();
var encoded = et.GetTxCount(address);
encoded.Wait();
}
How should I call the GetTxCount from a unit test to get the actual result.
I have used the "wait" command even though it is not recommended, but still cannot get it to return a result.
The Unit test bombs out - it does not even hit the API that Nethereum calls.
You have already made the test async then use async all the way through by using await to call GetTxCount
[TestMethod]
public async Task TestMethodAsync() {
string address = "0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae";
var et = new EthTest.Eth();
var encoded = await et.GetTxCount(address);
}
Given that GetTxCount is just returning the task then there really is no need to await it in the method.
Refactor to
public Task<HexBigInteger> GetTxCount(string address) {
return web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(address);
}
or
public async Task<HexBigInteger> GetTxCount(string address) {
var result = await web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(address).ConfigureAwait(false);
return result.
}
Reference Async/Await - Best Practices in Asynchronous Programming
In examples of using the ASP.NET Web API I see two different methods used to return data to the calling jQuery function. The first method returns an object of type Client but I am not sure what the second method is returning.
Method #1 (returns Client object)
public IEnumerable<Client> GetAllClients()
{
using (var context = new PQRSModel.PQRSEntities())
{
context.Configuration.ProxyCreationEnabled = false;
var query = context.Clients.OrderBy(c = c.OrgName);
var customers = query.ToList();
return customers;
}
}
Method #2 (What benefit does IHttpActionResult provide?)
public IHttpActionResult GetClient(int clientId)
{
using (var context = new PQRSModel.PQRSEntities())
{
context.Configuration.ProxyCreationEnabled = false;
var client = context.Clients.FirstOrDefault(c = c.ID == clientId);
if (client == null)
{
return NotFound();
}
return Ok(client);
}
}
If the second method finds a single object is there any reason it could not also return a Client object type?
Returning IHttpActionResult provides a nice separation of concerns.
Your controller can focus on responding to the request in the most sensible manner (status codes, error messages, etc.). Another (service) layer can focus on actually retrieving and transforming the business data.
The side-effect is, your controller methods become more unit testable. Consider the following simple example:
public class MyController : ApiController
{
//or better yet, dependency-inject this
SomeService _service = new SomeService();
public IHttpActionResult Get(int id)
{
if (id < 0)
return BadRequest("Some error message");
var data = _service.GetData(id);
if (data == null)
return NotFound();
return Ok(data);
}
}
Not only is this method's logic understandable just by reading it, but you could now test the logic more easily and naturally, something like (using NUnit syntax):
[TestFixture]
public class MyControllerTests
{
[Test]
public void Get_WithIdLessThan0_ReturnsBadRequest()
{
var controller = new MyController();
int id = -1;
IHttpActionResult actionResult = controller.Get(id);
Assert.IsInstanceOf<BadRequestErrorMessageResult>(actionResult);
}
}
Similarly, you could mock the Service layer and test what happens when you give known id parameters to the controller, etc.
Here is a good article on Unit Testing Controllers in Web Api
The second method allows you to return just status codes (like the 404 in the example), streaming file content and other types of non-object content.