Since 'func' is an async method that returns 'Task',a return keyword must not be followed by an object expression. Did you intend to return 'Task<T>'? - asp.net-core

Hello My Program got this error and i dont know why?
Since 'InsertToHomeSecondPagesTableJob.Execute(IJobExecutionContext)' is an async method that returns 'Task', a return keyword must not be followed by an object expression. Did you intend to return 'Task'?
this is my code
public async Task Execute(IJobExecutionContext context)
{
var PagesScoreNewsHomePageTable = new PagesScoreNewsHomePageTable()
{
PagesID = 1,
UserID = 22,
Author = "jack"
};
_db.AddAsync(PagesScoreNewsHomePageTable);
_db.SaveChangesAsync();
return Task.CompletedTask;
}
how can i solve this error?

The simple and recommended way to solve this problem is using await keywords.
The async and await keywords in C# are the heart of async programming.
By using those two keywords, you can use resources in .NET Framework,
.NET Core, or the Windows Runtime to create an asynchronous method
almost as easily as you create a synchronous method.
You just need to change your code like:
public async Task Execute(IJobExecutionContext context)
{
var PagesScoreNewsHomePageTable = new PagesScoreNewsHomePageTable()
{
PagesID = 1,
UserID = 22,
Author = "jack"
};
await _db.AddAsync(PagesScoreNewsHomePageTable);
await _db.SaveChangesAsync();
}
More details about async you can refer to this Docs.

Related

How to fill a Mock<DbSet> in Nunit with Moq?

I am trying to fill a mock dbset with a testentity but I only get exception after exception. I am very new to Nunit testing and haven't really got the hang of it. I am trying to test a simple delete method in my repository, here is the code for the method:
public async Task DeleteQuestion(Question questionToRemove)
{
if (questionToRemove is not null)
{
var questionsAnswers = await _context.Answers.Where(a => a.Question == questionToRemove).ToListAsync();
foreach (Answer a in questionsAnswers)
{
_context.Answers.Remove(a);
await _context.SaveChangesAsync();
}
_context.Questions.Remove(questionToRemove);
await _context.SaveChangesAsync();
var questions = await _context.Questions.Where(q => q.Quiz == questionToRemove.Quiz).ToListAsync();
int order = 1;
foreach (Question question in questions)
{
question.QuestionOrderId = order;
await _context.SaveChangesAsync();
order++;
}
}
}
And here is the test that I have written:
public async Task DeleteQuestionFunction()
{
//Arrange
Question testQuestion = new Question { QuestionId = 1, QuestionText = "Test" };
Answer testAnswer = new Answer { Question = testQuestion, AnswerId = 1, AnswerText = "TestAnswer" };
_appDBContextMock.SetupAdd(x => x.Questions.Add(testQuestion));
_appDBContextMock.SetupAdd(x => x.Answers.Add(testAnswer));
//Act
var questionListcomponent = new QuestionListComponent();
questionListcomponent.DeleteQuestion(testQuestion);
var testresult = await _questionRepositoryMock.Object.GetQuestionById(testQuestion.QuestionId);
//Assert
Assert.That(testresult, Is.Null);
}
When I only used the Setup method I got this exception:
System.NotSupportedException : Unsupported expression: x =>
x.Questions Non-overridable members (here: AppDbContext.get_Questions)
may not be used in setup / verification expressions.
and right now with the SetupAdd function I get this exception:
System.ArgumentException : Can not instantiate proxy of class:
TietoQuiz.Models.DbContexts.AppDbContext. Could not find a
parameterless constructor. (Parameter 'constructorArguments')
I think my problem is that I don't know how to set up a mock dbset properly. I tried to Google, but I found so many different ways and so many comments saying "that is not recommended/ the wrong way"! It is very confusing for a newbie, so I hope someone here can help!
If you want to write a test by using a context, you must create your own context and verify the data after running it. You cannot use mocks with non overridable methods.
You must use a temporary file to create this context not to change your production database.

EF Core not setting class variables automatically

I want to switch my code to an async implementation. When I want to do this then I notice that my related data gets not set automatically after I retrieve them like it used to do it.
This is the initial function that gets called from an API controller. I used the AddDbContext function to add the dbcontext class via dependency injection into my controller:
public async Task<Application> GetApplicationById(AntragDBNoInheritanceContext dbContext, int id)
{
List<Application> ApplicationList = await dbContext.Applications.FromSqlRaw("Exec dbo.GetApplication {0}", id).ToListAsync();
Application Application = ApplicationList.First();
if(Application != null)
{
await CategoryFunctions.GetCategoryByApplicationID(Application.Id);
}
}
The GetCategoryByApplicationId function loads the related category of an application which is a many to one relation between Category and Application:
public async Task<Category> GetCategoryByApplicationID(int applicationID)
{
var optionsBuilder = new DbContextOptionsBuilder<AntragDBNoInheritanceContext>();
optionsBuilder.UseSqlServer(ApplicationDBConnection.APPLICATION_CONNECTION);
using (var dbContext = new AntragDBNoInheritanceContext(optionsBuilder.Options))
{
List<Category> category = await dbContext.Categories.FromSqlRaw("Exec GetApplicationCategory {0}", applicationID).ToListAsync();
if (category.Any())
{
return category.First();
}
}
return null;
}
When I want to retrieve an application then the field Category is not set. When I did not use async/await it would set the category automatically for me. Of course I could just return the Category Object from the GetCategoryByApplicationId and then say:
Application.Category = RetrievedFromDbCategory;
But this seems a bit unmaintainable compared to the previous behaviour. Why does this happen now and can I do something about it? Otherwise I don't see much benefits on using async/await .

Custom Result in Net 6 Minimal API

In ASP.NET Core 5 I had a custom Action Result as follows:
public class ErrorResult : ActionResult {
private readonly IList<Error> _errors;
public ErrorResult(IList<Error> errors) {
_errors = errors;
}
public override async Task ExecuteResultAsync(ActionContext context) {
// Code that creates Response
await result.ExecuteResultAsync(context);
}
}
Then on a Controller action I would have:
return new ErrorResult(errors);
How to do something similar in NET 6 Minimal APIs?
I have been looking at it and I think I should implement IResult.
But I am not sure if that is the solution or how to do it.
I have recently been playing around with minimal APIs and and working on global exception handling. Here is what I have come up with so far.
Create a class implementation of IResult
Create a constructor which will take an argument of the details you want going into your IResult response. APIErrorDetails is a custom implementation of mine similar to what you'd see in ProblemDetails in MVC. Method implementation is open to whatever your requirements are.
public class ExceptionAllResult : IResult
{
private readonly ApiErrorDetails _details;
public ExceptionAllResult(ApiErrorDetails details)
{
_details = details;
}
public async Task ExecuteAsync(HttpContext httpContext)
{
var jsonDetails = JsonSerializer.Serialize(_details);
httpContext.Response.ContentType = MediaTypeNames.Application.Json;
httpContext.Response.ContentLength = Encoding.UTF8.GetByteCount(jsonDetails);
httpContext.Response.StatusCode = _details.StatusCode;
await httpContext.Response.WriteAsync(jsonDetails);
}
}
Return result in your exception handling middleware in your Program.cs file.
app.UseExceptionHandler(
x =>
{
x.Run(
async context =>
{
// https://learn.microsoft.com/en-us/aspnet/core/fundamentals/error-handling?view=aspnetcore-6.0
var exceptionFeature = context.Features.Get<IExceptionHandlerPathFeature>();
// Whatever you want for null handling
if (exceptionFeature is null) throw new Exception();
// My result service for creating my API details from the HTTP context and exception. This returns the Result class seen in the code snippet above
var result = resultService.GetErrorResponse(exceptionFeature.Error, context);
await result.ExecuteAsync(context); // returns the custom result
});
}
);
If you still want to use MVC (Model-View-Controller), you still can use Custom ActionResult.
If you just want to use Minimal APIs to do the response, then you have to implement IResult, Task<IResult> or ValueTask<IResult>.
app.MapGet("/hello", () => Results.Ok(new { Message = "Hello World" }));
The following example uses the built-in result types to customize the response:
app.MapGet("/api/todoitems/{id}", async (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? Results.Ok(todo)
: Results.NotFound())
.Produces<Todo>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound);
You can find more IResult implementation samples here: https://github.com/dotnet/aspnetcore/tree/main/src/Http/Http.Results/src
Link: Minimal APIs overview | Microsoft Docs

How to fetch initial data using provider in flutter effectievly

Recently, i did a flutter course.
The instructor was making the get request from an API so difficult. For a hybrid framework like flutter i never thought it's so difficult.
below are my code. I am using provider for state management.
Future<void> fetchAndSetProducts() async {
try {
const url = 'fetch-url';
final response = await http.get(url);
final data = json.decode(response.body) as Map<String, dynamic>;
final List<Product> loadedProducts = [];
data.forEach((key, value) {
loadedProducts.add(Product(
id: key,
title: value['title'],
description: value['description'],
imageUrl: value['imageUrl'],
price: value['price'],
isFavorite: value['isFavorite'],
));
});
_items = loadedProducts;
notifyListeners();
} catch (error) {
throw (error);
}
}
And in the products overview screen were I am showing the products page this method is called like below:
bool _isInit = true;
bool _isLoading = false;
#override
void didChangeDependencies() {
if (_isInit) {
setState(() {
_isLoading = true;
});
Provider.of<Products>(context).fetchAndSetProducts().then((_) => {
setState(() {
_isLoading = false;
})
});
}
_isInit = false;
super.didChangeDependencies();
}
The other method included a sneaky way of using duration of zero just like we use in javascript set timeout giving a zero time.
It's worth noting that in didChangeDependencies we could not use async await, so most probably a call back hell awaits.
Also a variable needs to be initialized just for calling the api once upon loading.
Is there no easy solution to this? Or an industry way of dealing with this?
here is a minimal working example of what you can do, it's not the best thing in the world, but this is what works for me, let me know if you can make it any better.
The answer to your problem is really simple, BUT, you need to rearrange some stuff first.
A Flutter app can be split into multiple layers which are (just for example) data, state management and UI, in the data layer you will have all methods that communicate with the API, and you call them inside the state management solution (which is provider in your case), the result will be accessible from the provider which will save the data in a variable, then the UI will be able to retrieve these data from the provider, this seems a bit redundant I know, but there is a reason why we do that, if you put the API call inside the provider itself, and there is somewhere else in your app that uses the same endpoint then you will have duplicate code, as for the provider, it's the place where your data is stored in the runtime, these data are what makes the state of your app, finally, the UI can handle displaying data from the provider easily, just make a boolean in the provider that indicates if the API call is executing/loading or not, and inside the consumer in the UI display different widgets based on the boolean.
If we were to visualize the flow of the operation it would be like this:
1- action from the UI that triggers a method from the provider.
2- inside the provider method you will set the boolean indicating that the API call is executing to true and call notifyListeners().
3- call the API request and call .then() on it.
4- inside the .then() set the boolean to false to notify that the call is over and set the received data to a variable inside the provider and call notifyListeners again.
5- in the UI you should have a consumer listening to your provider and handling the boolean, if its true then display a CircularProgressIndicator for example, and if it's false then display your desired widget
Regarding the context in the initState you can fix this problem in 3 ways:
1- using WidgetsBinding.instance
.addPostFrameCallback((_) => yourProviderFunction(context));
2- by registering your provider in a service locator so you don't have to use a context at all. (which is what I used in the example project I posted above)
3- by executing the desired function in the constructor of the provider, so when its initialized the API request will be called
Is this the Academind course?
Also this is the correct way.
For using a Provider you need the context.
EDIT: Added BaselAbuhadrous' comment to the answer.
You need to use didChangeDependencies because the initState actually provides the context, but the screen layout isn't built yet, so you get an error, but if you used WidgetsBindings.instance and call the provider inside of it, then you won't get the error.
//your model , product_model.dart
import 'dart:convert';
List<Product> availableTicketsFromJson(String str) => List<Product>.from(json.decode(str).map((x) => Product.fromJson(x)));
class Product {
String title;
String description;
String imageUrl;
double price;
bool isFavorite;
Product(
{this.title,
this.description,
this.imageUrl,
this.price,
this.isFavorite});
factory Product.fromJson(Map<String, dynamic> json) => Product(
title: json['title'] as String,
description: json['description'] as String,
imageUrl: json['imageUrl'] as String,
price: json['price'] as double,
isFavorite: json['isFavorite'] as bool,
);
}
//viewmodel class
final String url = "test.com";
Future<List<Product> fetchProducts() async {
List<Product> products = List<Product>();
try {
final request = await http.get(url);
if(request.statusCode == 200) {
products = productsFromJson(request.body.toString());
notifyListeners();
} else {
print(request.statusCode.toString());
}
} catch(e) {
return List<Product>();
}
return products;
}
//fetch_data.dart
Create your instance of provider in the page that you wanna fetch the data:
Under State<yourWidget>
=> FetchDataViewModel _model;
List<Product> products = [];
under build method
=> _model = Provider.of<FetchDataViewModel>(context,listen: false);
Make a http request with FutureBuilder
FutureBuilder(future:_model.fetchProducts()),
builder: (context,snapshot)){
if(snapshot.connectionState == ConnectionState.done) {
products = snapshot.data;
if(products.length > 0) {
return ListView.builder(
itemCount: products.length,
itemBuilder : (context,index) {
return _items();
}
);
} else {return _noSavedDataWidget();}
}
}
You can test such a code
sometimes
Provider.of<'providerClassName'>(context, listen : false).'providerFunction'
might help.

retrieve int value from async task

I have an async task in a separate project that I need to call from another project but Im not sure how to accomplish that.
The async method is
public async Task<int> InsertNewPasswordResetRequest(UserPasswordReset upr)
{
string commandText = "Insert Into passwordresetrequests (reset_username, ResetToken, ResetRequestTime, ResetRequestTimeout) values(#username,#rt,#rrt,#rrtout);";
var parameters = new Dictionary<string, object>() {
{ "#username", upr.ResetUsername },
{ "#rt", upr.ResetToken },
{ "#rrt", upr.ResetRequestTime },
{ "#rrtout", upr.ResetRequestTimeout }
};
return await Task.FromResult( _database.Execute(commandText, parameters, false));
}
I am trying to call it from another project like so
Dim success As Integer = prr.InsertNewPasswordResetRequest(upr).FromResult()
I know its returning a task but how do I extract the int value from it?
You can await of your task if you want to run it async
Dim success As Integer = Await prr.InsertNewPasswordResetRequest(upr)
or run task synchronously as
Dim success As Integer = prr.InsertNewPasswordResetRequest(upr).Result
The recommended way is to await the results of the InsertNewPasswordResetRequest method. You can also call the Result property on the returned Task<int> but that could lead to your code blocking if you're executing within a synchronization context.
int result = await InsertNewPasswordResetRequest(...);
An additional note: There is no need to await Task.FromResult in that method. Simply remove the async modifier from the method signature and the await keyword and return Task.FromResult directly.
An additional note: If possible, consider making InsertNewPasswordResetRequest non-async completely since it doesn't execute any asynchronous code.
Edit for VB.NET calling code:
Dim result As Integer = Await InsertNewPasswordResetRequest(...)