Make a parameter in minimal api as an optional in .NET Core - api

I have this API as you can see:
app.MapGet("/api/fund/{fundCode}", ([FromServices] IMediator mediator,string fundCode)
=> mediator.Send(new GetFundsQuery(fundCode)));
I want to set fundcode as an optional parameter to my API, so I changed it to
app.MapGet("/api/fund/{fundCode?}", ([FromServices] IMediator mediator,string fundCode)
=> mediator.Send(new GetFundsQuery(fundCode)));
But it didn't work, and when I call this address
https://localhost:7147/api/fund
I get an http 404 error. Why?

When I used code below, I'll get "null" as a response when I call localhost:port/hello. But when I use string id as the parameter, I got 400 bad request...
app.MapGet("/hello/{id?}", (string? id) =>
{
if (id == null)
{
return "null";
}
else {
return id;
}
});
I also tried to use code below and when I call localhost:port/hello, I get "empty" as the response.
app.MapGet("/hello/{id?}", (string? id) =>
{
if (id == null)
{
return "null";
}
else {
return id;
}
});
app.MapGet("/hello", () =>
{
return "empty";
});

You can try the query parameter. For example:
app.MapGet("/api/fund", GetFundsAsync).Produces<IList<Fund>>();
private async Task<IList> GetFundsAsync(IMediator mediator,string fundCode = null)
{
return await mediator.Send(new GetFundsQuery(fundCode));
}
This way https://localhost:7147/api/fund will return results
And https://localhost:7147/api/fund?fundCode=ABC will work too

Related

error: A value of type 'LocationModel' can't be returned from method 'getLocation' because it has a return type of 'List<dynamic>'

Future<List> getLocation(String city,DateTime date) async {
try {
http.Response hasil = await http.get(
Uri.encodeFull(
"https://api.pray.zone/v2/times/day.json?city=${city}&date=${date}"),
headers: {"Accept": "Application/json"});
if (hasil.statusCode == 200) {
print("Location Successfully Gathered");
final data = locationModelFromJson(hasil.body);
return data;
} else {
print("Error Status ${hasil.statusCode.toString()}");
}
} catch (e) {
print("error catch $e");
return null;
}
}
why cant i return the data variable? it says that because the model has a return type List<dynamic>
edit:
my Model is https://textuploader.com/1pmb6
As you can see, the data you are fetching and parsing is LocationModel.fromJson and you are returning it. But the return type of your method is Future<List> so clearly you are not returning the type that you mentioned the method would.
The correct implementation would be this,
Future<LocationModel> getLocation(String city,DateTime date) async {
...
}
if your API is returning a List of LocationModel which is why I assume you mentioned list,
then you will have to do this,
Future<List<LocationModel> getLocation(String city,DateTime date) async {
try {
http.Response hasil = await http.get(
Uri.encodeFull(
"https://api.pray.zone/v2/times/day.json?city=${city}&date=${date}"),
headers: {"Accept": "Application/json"});
if (hasil.statusCode == 200) {
print("Location Successfully Gathered");
List<LocationModel> locs =[];
hasil.forEach((d){
final l = locationModelFromJson(d.body);
locs.add(l);
});
return locs;
} else {
print("Error Status ${hasil.statusCode.toString()}");
}
} catch (e) {
print("error catch $e");
return null;
}
}
Dart is a very strictly typed language, so if you do not mention a type, Dart assumes that it is dynamic by default and hence you get that error.

Flutter : How to delete Rest Api Using Http.Client?

I develope App for CRUD Operation rest api using Http Client. GET and POST work perfectly, but problem come after DELETE Operation.
Console Message show me response code Bad Request 400 **, I Check code rest Api (in my codeigniter) **Bad Request 400 it's means the ID is null or not passing the ID on URL Rest Api.
It's Console Message Image
But I try on POSTMAN and **DELETE* is perfectly work , i dont know why in flutter http.delete not working.
It's Result POSTMAN Working
My Api Url for Delete
http://192.168.43.159/wpu-rest-server/apii/mahasiswa/delete/
It's My API.dart :
Future<bool> checkPost(Map<String, dynamic> id) async {
final client = http.Client();
try {
final response = await client.send(http.Request(
"DELETE", Uri.parse("${Urls.BASE_API_URL}mahasiswa/delete/"))
..headers['Content-type']= 'application/x-www-form-urlencoded'
..body = jsonEncode(id));
print(response.reasonPhrase);
print(response.statusCode.toString());
print(response.request.toString());
return response.statusCode == 204;
} finally {}
}
It's My list.dart :
void _checkPost() async{
final post = {"id":widget.id};
bool result = await api.checkPost(post);
if (result) {
_showSnackBar(
context, 'Success ');
} else {
_showSnackBar(context, 'Failed');
return null;
}
}
If you need Rest Api Code :
Controller
public function delete_delete()
{
$id = $this->delete('id');
$msgDelete = ['id' => $id, 'message' => 'Deleted the resource'];
$msgEmpty = ['status' => false, 'message' => 'ID Not Found'];
$msgBadRequest = ['status' => false, 'message' => 'Provide an ID'];
if ($id === null) {
$this->set_response($msgBadRequest, 400);
} else {
if ($this->mahasiswa->deleteMahasiswa($id) > 0) {
$this->set_response($msgDelete, 204);
} else {
$this->set_response($msgEmpty, 404);
}
}
}
Model
public function deleteMahasiswa($id = null)
{
if ($id === null) {
return false;
} else {
$this->db->delete('mahasiswa', ['id' => $id]);
return $this->db->affected_rows();
}
}
I'm mistake something ?
I ever heard httpclient.delete can't add body , but in POSTMAN need add body for deleting data, how to handle this ?

Flutter: BLoC, testing streams

Testing the bloc pattern is not so clear to me. So, if I have these 2 stream controllers:
final _controller1 = StreamController();
final _controller2 = StreamController<bool>;
Sink get controller1Add = _controller1.sink;
Stream<bool> get controller2Out = _controller2.stream;
and I want to test that, from this function:
submit() {
if (_controller1.value == null ||
_controller1.value.isEmpty) {
print(...)
return;
}else
_controller2.sink.add(true);
}
the _controller2.stream should have true, how should I do?
I tried something like:
test("test", (){
bloc.submit();
expect(bloc.controller2Out, emitsAnyOf([true]));
});
but, of course, it didnĀ“t work.
I've modified your code to use the RxDart's BehaviorSubject and it seems to work. You are using StreamController but I get error cause it doesn't have the value property.
final _controller1 = BehaviorSubject<String>();
final _controller2 = BehaviorSubject<bool>();
Sink get controller1Add => _controller1.sink;
Stream<bool> get controller2Out => _controller2.stream;
submit() {
if (_controller1.value == null || _controller1.value.isEmpty) {
print('Error');
_controller2.sink.add(false);
return;
} else {
print('OK');
_controller2.sink.add(true);
}
}
The test:
bloc.controller1Add.add('');
bloc.submit();
expect(bloc.controller2Out, emits(false));
bloc.controller1Add.add('test');
bloc.submit();
expect(bloc.controller2Out, emits(true));
bloc.controller1Add.add('');
bloc.submit();
expect(bloc.controller2Out, emits(false));

Get JavaScript Array of Objects to bind to .Net Core List of ViewModel

I have a JS Array of Objects which, at time of Post contains three variables per object:
ParticipantId,
Answer,
ScenarioId
During post, there is an Array the size of 8 (at current anyway) which all correctly contain data. When I call post request, the Controller does get hit as the breakpoint triggers, the issue is when I view the List<SurveyResponse> participantScenarios it is shown as having 0 values.
The thing I always struggle to understand is that magic communication and transform between JS and .Net so I am struggling to see where it is going wrong.
My JS Call:
postResponse: function () {
var data = JSON.stringify({ participantScenarios: this.scenarioResponses})
// POST /someUrl
this.$http.post('ScenariosVue/PostScenarioChoices', data).then(response => {
// success callback
}, response => {
// error callback
});
}
My .Net Core Controller
[HttpPost("PostScenarioChoices")]
public async Task<ActionResult> PostScenarioChoices(List<SurveyResponse> participantScenarios)
{
List<ParticipantScenarios> addParticipantScenarios = new List<ParticipantScenarios>();
foreach(var result in participantScenarios)
{
bool temp = false;
if(result.Answer == 1)
{
temp = true;
}
else if (result.Answer == 0)
{
temp = false;
}
else
{
return StatusCode(400);
}
addParticipantScenarios.Add(new ParticipantScenarios
{
ParticipantId = result.ParticipantId,
Answer = temp,
ScenarioId = result.ScenarioId
});
}
try
{
await _context.ParticipantScenarios.AddRangeAsync(addParticipantScenarios);
await _context.SaveChangesAsync();
return StatusCode(201);
}
catch
{
return StatusCode(400);
}
}

Yii::app()->user->isGuest always returns true even though login was successful

I started to make some differences between those users which have authenticated and those that not. For this, i am using
Yii::app()->user->id;
However, in a determined view i put the following code:
<?php
if(Yii::app()->user->isGuest) {
print("Welcome back Guest!");
print("Your id is ".Yii::app()->user->id);
} else {
print("Welcome back ".Yii::app()->user->name);
print("Your id is ".Yii::app()->user->id);
}?>
And i always get the "welcome back guest!", whether i have logged in (successfully) or not. And if i have logged in, then it displays the welcome message together with the user's id!
EDIT
#briiC.lv
Hey.. sorry for the late reply, I hope you are still following this! I am not extending the given UserIdentity class. Is this mandatory? Since i still dont get very well the whole authorization issue, i thought it would be best to give a try with the class they provide, and then extend with my own functionality.. Anyway, next i post my UserIdentity class with its small tweaks.. maybe the problem lies here??
<?php class UserIdentity extends CUserIdentity{
private $_id;
public function authenticate()
{
$user = Users::model()->findAll('username=\''.$this->username.'\' AND password=\''.$this->encryptedPassword.'\'');
if(!isset($user[0]))
{
return false;
}
else
{
$this->setState('id', $user[0]->id);
$this->username = $user[0]->username;
$this->errorCode=self::ERROR_NONE;
return true;
}
}
public function getId()
{
return $this->_id;
}
}
Here is the output i got when i started to log as you suggested; i got this output immediately after successfully logging in.
[05:23:21.833][trace][vardump] CWebUser#1 (
[allowAutoLogin] => true
[guestName] => 'Guest'
[loginUrl] => array ( '0' => '/site/login' )
[identityCookie] => null
[authTimeout] => null
[autoRenewCookie] => false
[autoUpdateFlash] => true
[CWebUser:_keyPrefix] => '0f4431ceed8f17883650835e575b504b'
[CWebUser:_access] => array()
[behaviors] => array()
[CApplicationComponent:_initialized] => true
[CComponent:_e] => null
[CComponent:_m] => null
)
Any help is much appreciated!
Maybe you can try to debug harder:
change messages to something like this:
if(Yii::app()->user->isGuest) {
print("Not logged");
} else {
print_r(Yii::app()->user);
print("Welcome ".Yii::app()->user->name);
print("Your id is ".Yii::app()->user->id);
}
And check session variable in your config/main.php file
...
'session' => array(
'autoStart'=>true,
),
...
The error is in the following line
$this->setState('id', $user[0]->id);
As seen in the official yii documentation regarding auth & auth, setState should be used for anything but the id field. In order to implement the key Yii will use to identify your user, return a unique value per user in the Identity getId() function.
In your case, this means you simply have to change the above line into the following:
$this->_id = $user[0]->id;
Regarding the actual inner working of the login procedure, I'd recommend a look at the CWebUser class, and especially at its login function, which is responsible for the actual storage of the Identity getId() return value.
when you call authenticate function login user as
$userIdentity = new UserIdentity($username, $password);
$userIdentity->authenticate();
if ($userIdentity->errorCode===UserIdentity::ERROR_NONE) {
Yii::app()->user->login($userIdentity,0);
}
and fetch id as
echo 'id='.Yii::app()->user->getId();
apply this code and check
I have faced same problem and found that only one line in UserIdentity Component will resolve this issue.
This is your code:
else
{
$this->setState('id', $user[0]->id);
$this->username = $user[0]->username;
$this->errorCode=self::ERROR_NONE;
return true;
}
Update this code by this one
else
{
$this->_id = $user[0]->id;
$this->setState('id', $user[0]->id);
$this->username = $user[0]->username;
$this->errorCode=self::ERROR_NONE;
return true;
}
First of all, you need to know condition that sets guest and logged-in user apart.
Based on Yii master's branch CWebUser::getIsGuest():
public function getIsGuest()
{
return $this->getState('__id')===null;
}
Compared to your code:
$user = Users::model()->findAll('username=\''.$this->username.'\' AND password=\''.$this->encryptedPassword.'\'');
if(!isset($user[0])) {
// false
} else {
$this->setState('id', $user[0]->id); // this is for persistent state sakes
...
}
}
In short: you did supply 'id' to Identity persistent state but Yii CWebUser expecting '__id' based on UserIdentity::getId().
Solution is pretty dead simple. You just need to set $this->_id
$user = Users::model()->findAll('username=\''.$this->username.'\' AND password=\''.$this->encryptedPassword.'\'');
if(!isset($user[0])) {
// false
} else {
$this->setState('id', $user[0]->id); // this is for persistent state sakes
$this->_id = $user[0]->id; // this is UserIdentity's ID that'll be fetch by CWebUser
...
}
}
This routine explains how CWebUser get UserIdentity's ID: https://github.com/yiisoft/yii/blob/master/framework/web/auth/CWebUser.php#L221
Please do test it out.
Please try following code. Its working well
//config/main.php
return array (
'component' => array(
'session' => array(
'savePath' => INSTANCE_ROOT.DS.'runtime'.DS.'session',
'autoStart' => true,
),
)
);
// LoginController
class LoginController extends CController {
public function actionLogin () {
if(isset($_POST['LoginForm']))
{
$form = new LoginForm;
$form->setAttributes($_POST['LoginForm']);
if ($form->validate()) {
$user = Users::model()->find('upper(username) = :username', array(
':username' => strtoupper($form->username)));
if($user)
return $this->authenticate($user, $form);
else {
Yii::log( 'som.....', 'error');
$form->addError('password', Yii::t('Username or Password is incorrect'));
}
return false;
}
}
}
protected function authenticate($user, $form) {
$identity = new UserIdentity($user->username, $form->password);
$identity->authenticate();
switch($identity->errorCode) {
case UserIdentity::ERROR_NONE:
$duration = $form->rememberMe ? 3600*24*30 : 0; // 30 days
Yii::app()->user->login($identity,$duration);
return $user;
break;
case UserIdentity::ERROR_EMAIL_INVALID:
$form->addError("password",Yii::t('Username or Password is incorrect'));
break;
case UserIdentity::ERROR_STATUS_INACTIVE:
$form->addError("status",Yii::t('This account is not activated.'));
break;
case UserIdentity::ERROR_STATUS_BANNED:
$form->addError("status",Yii::t('This account is blocked.'));
break;
case UserIdentity::ERROR_STATUS_REMOVED:
$form->addError('status', Yii::t('Your account has been deleted.'));
break;
case UserIdentity::ERROR_PASSWORD_INVALID:
Yii::log( Yii::t(
'Password invalid for user {username} (Ip-Address: {ip})', array(
'{ip}' => Yii::app()->request->getUserHostAddress(),
'{username}' => $form->username)), 'error');
if(!$form->hasErrors())
$form->addError("password",Yii::t('Username or Password is incorrect'));
break;
return false;
}
}
}
class UserIdentity extends CUserIdentity {
const ERROR_EMAIL_INVALID=3;
const ERROR_STATUS_INACTIVE=4;
const ERROR_STATUS_BANNED=5;
const ERROR_STATUS_REMOVED=6;
const ERROR_STATUS_USER_DOES_NOT_EXIST=7;
public function authenticate()
{
$user = Users::model()->find('username = :username', array(
':username' => $this->username));
if(!$user)
return self::ERROR_STATUS_USER_DOES_NOT_EXIST;
if(Users::encrypt($this->password)!==$user->password)
$this->errorCode=self::ERROR_PASSWORD_INVALID;
else if($user->status == YumUser::STATUS_INACTIVE)
$this->errorCode=self::ERROR_STATUS_INACTIVE;
else if($user->status == YumUser::STATUS_BANNED)
$this->errorCode=self::ERROR_STATUS_BANNED;
else if($user->status == YumUser::STATUS_REMOVED)
$this->errorCode=self::ERROR_STATUS_REMOVED;
return !$this->errorCode;
}
}
class Users extends CActiveModel
{
const STATUS_INACTIVE = 0;
const STATUS_ACTIVE = 1;
const STATUS_BANNED = -1;
const STATUS_REMOVED = -2;
// some ..........
public static function encrypt($string = "")
{
$salt = 'salt';
$string = sprintf("%s%s%s", $salt, $string, $salt);
return md5($string);
}
}
check your security configuration for cookies and sessions.
disable session.use_only_cookies & session.cookie_httponly in php.ini
file.
in PHP.INI => session.use_only_cookies = 0