I am developing an app with Flutter and Firebase.
I want to store the _id with SharedPreferences permanently.
Therefore, i looked after it, but my code doesnt work at all.
It always throws the error:
type 'Future' is not a subtype of type 'String'
Here is my code:
class Profile with ChangeNotifier {
String _id;
void setName(String name) {
const url =
'myurl';
http
.post(url, body: json.encode({'name': name, 'description': name}))
.then((response) {
_id = json.decode(response.body)['name'];
});
addID();
}
Future<void> updateName(String name, String id) async {
String url =
'myurl';
await http.patch(url,
body: json.encode({'name': 'Ein Titel', 'description': name}));
}
And here are my methods with the SharedPrefs:
String getID() {
return getIDOffline();
}
addID() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('id', _id);
}
getIDOffline() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
//Return String
String stringValue = prefs.getString('id');
return stringValue;
}
Try this:
void setName(String name) {
const url = 'myurl';
var body = json.encode({'name': name, 'description': name});
var response = await http.post(url, body: body);
String id = json.decode(response.body)['name'];
addID(id);
}
addID(id) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('id', id);
}
Future<String> getID() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
//Return String
String stringValue = prefs.getString('id');
return stringValue;
}
Your getID is async function so it return Future and not String..
Related
On the button click event of React side I am calling a node backend.
click event of react,
// calling node backend
this.uploadApi.command(postData.bin_files, this.dummy);
this.setState({submit_form});
}
dummy = (result)=>{
console.log(result);
}
This is my Node backend code,
import axios from 'axios';
class UploadFile {
constructor() {
this.url = 'http://localhost:56246/microservice/uploaddata'; //This is the local MVC application's URL (microservice is the controller)
}
command(postData, callback, uploadCallback = null) {
let jsonDataString = JSON.stringify(postData).replace(/&/g, '--and--');
jsonDataString = jsonDataString.replace(/\+/g, '--plus--');
const payload = JSON.parse(jsonDataString);
console.log('----------');
console.log(this.url);
console.log(payload);
console.log('----------');
// var data = qs.stringify({'jsondata':payload});
const data = new FormData();
for (var i = 0; i < payload.length; i++) {
console.log('inside for 1');
data.append(`model[${i}].name`, payload[i].name);
data.append(`model[${i}].bin_file`, payload[i].bin_file);
console.log('inside for 2');
}
console.log('=============');
console.log(data);
console.log('=============');
var config = {
method: 'post',
url: this.url,
headers: {
'Content-Type': 'multipart/form-data'
},
data: "jsondata=" + data,
onUploadProgress: (progressEvent) => {
const {
loaded,
total
} = progressEvent;
console.log("loaded:", loaded);
console.log("total:", total);
if (uploadCallback !== null) uploadCallback(progressEvent);
}
};
axios(config)
.then(function(response) {
// console.log(JSON.stringify(response.data));
callback(response.data);
})
.catch(function(error) {
console.log(error);
});
// axios.post(this.url, data)
// .then(res => console.log(res.data))
// .catch((error) => { console.error(error) });
}
}
export default UploadFile;
And this is my respective controller,
public dynamic UploadData(List<MemberInfo> model)
{
using (SqlConnection conn = new SqlConnection())
{
conn.ConnectionString = mstrDBConStringNew;
conn.Open();
SqlCommand command = new SqlCommand("SELECT * from tempstorage", conn);
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
//port = reader.GetString(0);
}
}
}
return "Hiiiiiiii";
}
public class MemberInfo
{
public string name { get; set; }
public string bin_file { get; set; }
}
Now If I show You while debugging, the controller and its respective action gets called but the value that I am expecting is null.
I have also tried like this way, but no luck
public dynamic UploadData(FormCollection model)
{
using (SqlConnection conn = new SqlConnection())
{
conn.ConnectionString = mstrDBConStringNew;
conn.Open();
SqlCommand command = new SqlCommand("SELECT * from tempstorage", conn);
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
//port = reader.GetString(0);
}
}
}
return "Hiiiiiiii";
}
This is my network request,
Please ask if anything additional is needed.
Yes I was able to figure out the issue,
var config = {
method: 'post',
url: this.url,
headers: {
'Content-Type': 'multipart/form-data'
},
data: data, // previously it was, "jsondata=" + data
Here I am getting the data as expected..
What is the best way to get a jwt token from a running NodeJS server, in a C# .NET Windows app?
in .NET I use HttpClient to connect to an oauth2 server (and that succeeds), but how to get the very jwt token?
In NodeJS:
const express = require('express')
const https = require('https');
const axios = require('axios');
var url = require('url');
const app = express()
const port = 3000
const agent = new https.Agent({ rejectUnauthorized: false });
async function get_token() {
try {
let url = "https://oauthservername/token.oauth2";
let formfields = "client_id=cid&grant_type=password&validator_id=ourAuthNG&client_secret=secretstring&username=billy&password=xxxxxxxxx";
let response = await axios.post(url, formfields, { httpsAgent: agent });
console.log(response.data);
} catch (error) {
console.log(error);
}
}
app.get('/token', (req, res) => {
get_token();
res.send('Eureka!');
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
This is working. I am getting the "Eureka!", in Postman as well as in my .NET HttpClient call
In my console I am getting (x-ing original info...), (output from console.log(response.data);)
{
access_token: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
refresh_token: 'xxxxxxxxxxxxxxxxx',
token_type: 'Bearer',
expires_in: 28799
}
So, in my C# code I do this (also getting "Eureka!", I see it in the responseBody):
private async void cmdConnectServer_Click(object sender, EventArgs e)
{
//client is HttpClient
client.BaseAddress = new Uri("http://localhost:3000/");
HttpResponseMessage response = await client.GetAsync("http://localhost:3000/token");
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
}
But how to get the very token?
In NodeJS you never send the token result in the api response, modify it like this :
async function get_token() {
try {
let url = "https://oauthservername/token.oauth2";
let formfields = "client_id=cid&grant_type=password&validator_id=ourAuthNG&client_secret=secretstring&username=billy&password=xxxxxxxxx";
let response = await axios.post(url, formfields, { httpsAgent: agent });
console.log(response.data);
//Return the oauth2 result
return response.data;
} catch (error) {
console.log(error);
}
}
app.get('/token', (req, res) => {
//sending 'Eureka!' is pointless, instead send the token result
res.send(get_token());
})
In c#
using System;
using System.Runtime.Serialization;
using System.Text.Json;
... ...
//Class for response deserialization
[Serializable]
public class TokenResult
{
[DataMember]
public string access_token { get; set; }
[DataMember]
public string refresh_token { get; set; }
[DataMember]
public string token_type { get; set; }
[DataMember]
public long expires_in { get; set; }
}
private async void cmdConnectServer_Click(object sender, EventArgs e)
{
//client is HttpClient
client.BaseAddress = new Uri("http://localhost:3000/");
HttpResponseMessage response = await client.GetAsync("http://localhost:3000/token");
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
// Deserialize the token response and get access_token property
string token = JsonSerializer.Deserialize<TokenResult>(responseBody ).access_token;
}
Or just don't use node js and do everything in c#
using System;
using System.Runtime.Serialization;
using System.Text.Json;
... ...
//Class for response deserialization
[Serializable]
public class TokenResult
{
[DataMember]
public string access_token { get; set; }
[DataMember]
public string refresh_token { get; set; }
[DataMember]
public string token_type { get; set; }
[DataMember]
public long expires_in { get; set; }
}
public string get_token()
{
HttpClientHandler OpenBarHandler = new HttpClientHandler { ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator };
HttpClient _httpClient = new HttpClient(OpenBarHandler);
_httpClient.BaseAddress = new Uri("https://oauthservername/token.oauth2");
HttpRequestMessage mess = new HttpRequestMessage();
mess.Method = HttpMethod.Post;
mess.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Dictionary<string, string> _parameters = new Dictionary<String, String>();
_parameters.Add("grant_type", "password");
_parameters.Add("username", "billy");
_parameters.Add("password", "xxxxxxxxx");
_parameters.Add("client_id", "cid");
_parameters.Add("client_secret", "secretstring");
_parameters.Add("validator_id", "ourAuthNG");
FormUrlEncodedContent encodedContent = new FormUrlEncodedContent(_parameters);
encodedContent.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
mess.Content = encodedContent;
HttpResponseMessage response = _httpClient.SendAsync(mess).Result;
if (response.IsSuccessStatusCode)
{
string strResp = response.Content.ReadAsStringAsync().Result;
return JsonSerializer.Deserialize<TokenResult>(strResp).access_token;
}
else
throw new Exception("Token retrieval failed");
}
I expected that validate() function of child class returns the type of checks() child class function. But as you see it returns the type of parent class function.
Playground
Could you explain why and how to fix it?
class Test {
process() {
const attrs = this.validate(); // (method) Test.validate(): void
return attrs;
}
validate() {
const attrs = this.checks();
return attrs;
}
protected checks() {}
}
class SubTest extends Test {
process() {
const attrs = this.validate(); // (method) Test.validate(): void
return attrs;
}
protected checks() {
return 'hello';
}
}
class Test {
process() {
const attrs = this.validate(); // (method) Test.validate(): void
return attrs;
}
validate<T>(): T {
const attrs = this.checks();
return attrs;
}
protected checks(): any {}
}
class SubTest extends Test {
process() {
const attrs = this.validate<ReturnType<SubTest['checks']>>(); // (method) Test.validate(): Number
return attrs;
}
protected checks(): Number {
return 1;
}
}
class Sub2Test extends Test {
process() {
const attrs = this.validate<ReturnType<Sub2Test['checks']>>(); // (method) Test.validate(): String
return attrs;
}
protected checks(): String {
return 'ssssss';
}
}
const instance = new SubTest();
const response = instance.process();
console.log(response);
Instead of below list. I want to fetch the Username and Password from session
private List _users = new List
{
new User { Id = 1, FirstName = "Jeevan", LastName = "Nigade", Username = "Jeevan", Password = "jeevan" }
};
This is my controller Code :-
[Route("api")]
[ApiController]
public class UsersController : ControllerBase
{
private IUserService _userService;
public UsersController(IUserService userService)
{
_userService = userService;
}
[HttpPost("token")]
public IActionResult Authenticate([FromBody]User userParam)
{
//var user
try
{
if (string.IsNullOrEmpty(userParam.Username))
{
return StatusCode(400, "Username Cannot Be Null..!!");
}
else if (string.IsNullOrEmpty(userParam.Password))
{
return StatusCode(400, "Password Cannot Be Null..!!");
}
else
{
var user = _userService.Authenticate(userParam.Username, userParam.Password);
if (user == null)
{
return StatusCode(400,"Username or password is incorrect..!!");
}
return Ok(user);
}
}
catch(Exception ex)
{
return StatusCode(500, ex.Message);
}
}
[Authorize]
[HttpGet("private")]
public IActionResult GetAll()
{
var users = _userService.GetAll();
return Ok(users);
}
}
Below is my class UserServie.cs code :-
public class UserService : IUserService
{
private List<User> _users = new List<User>
{
new User { Id = 1, FirstName = "Jeevan", LastName = "Nigade", Username = "Jeevan", Password = "jeevan" }
};
private readonly AppSettings _appSettings;
public UserService(IOptions<AppSettings> appSettings)
{
_appSettings = appSettings.Value;
}
public User Authenticate(string username, string password)
{
var user = _users.SingleOrDefault(x => x.Username == username && x.Password == password);
if (user == null)
return null;
var tokenHandler = new JwtSecurityTokenHandler();
var ClientValues = _appSettings.ClientId + _appSettings.ClientSecret;
var key = Encoding.ASCII.GetBytes(ClientValues);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.Name, user.Id.ToString())
}),
//Expires = DateTime.UtcNow.AddSeconds(10),
Expires = DateTime.Now.AddSeconds(10),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
user.Token = tokenHandler.WriteToken(token);
user.Password = null;
return user;
}
public IEnumerable<User> GetAll()
{
return _users.Select(x => {
x.Password = null;
return x;
});
}
}
where I have set the list value.
In this where and how can i set the Session value and how do i fetch it.
From your code,the user list seems to be all the users.I suggest that you could get them like below:
var user = _context.User.ToList();
For you want to set session and get it.Here is a working demo like below:
1.Controller.cs
public class UsersController : ControllerBase
{
private IUserService _userService;
public const string SessionKeyName = "user";
public UsersController(IUserService userService)
{
_userService = userService;
}
[HttpPost("token")]
public IActionResult Authenticate([FromBody]User userParam)
{
var users = new User { Id = 1, FirstName = "Jeevan", LastName = "Nigade", Username = "Jeevan", Password = "jeevan" };
HttpContext.Session.SetComplexData(SessionKeyName, users);
var _users = HttpContext.Session.GetComplexData<User>(SessionKeyName);
try
{
if (string.IsNullOrEmpty(userParam.Username))
{
return StatusCode(400, "Username Cannot Be Null..!!");
}
else if (string.IsNullOrEmpty(userParam.Password))
{
return StatusCode(400, "Password Cannot Be Null..!!");
}
else
{
var user = _userService.Authenticate(userParam.Username, userParam.Password,_users);
if (user == null)
{
return StatusCode(400, "Username or password is incorrect..!!");
}
return Ok(user);
}
}
catch (Exception ex)
{
return StatusCode(500, ex.Message);
}
}
[Authorize]
[HttpGet("private")]
public IActionResult GetAll()
{
var _users = HttpContext.Session.GetComplexData<User>(SessionKeyName);
var users = _userService.GetAll(_users);
return Ok(users);
}
2.UserService:
public class UserService : IUserService
{
public User Authenticate(string username, string password,User _users)
{
if (_users.Username == username && _users.Password == password)
return _users;
return null;
}
public User GetAll(User _users)
{
return _users;
}
}
3.IUserService:
public interface IUserService
{
User Authenticate(string username, string password,User _users);
User GetAll(User _users);
}
4.SessionExtensions:
public static class SessionExtensions
{
public static T GetComplexData<T>(this ISession session, string key)
{
var data = session.GetString(key);
if (data == null)
{
return default(T);
}
return JsonConvert.DeserializeObject<T>(data);
}
public static void SetComplexData(this ISession session, string key, object value)
{
session.SetString(key, JsonConvert.SerializeObject(value));
}
}
5.Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSingleton<IUserService, UserService>();
services.AddSession();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseSession();
app.UseMvc();
}
My Xamarin.Forms mobile app uses a Web Api and Asp.Net Identity to register the user and store the information in a default Azure table called dbo.AspNetUsers. I would like to check whether the record exists before registering the user and return a relevant message if the user already exists (email should be unique in this case).
In my Web Api:
[Route("Register")]
public async Task<IHttpActionResult> Register(RegisterBindingModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var user = new ApplicationUser() { UserName = model.Email, Email = model.Email, FirstName = model.FirstName, LastName = model.LastName, Region = model.Region };
IdentityResult result = await UserManager.CreateAsync(user, model.Password);
if (!result.Succeeded)
{
return GetErrorResult(result);
}
return Ok();
}
In my Xamarin.Forms PCL:
public class RegisterBindingModel
{
public string Email { get; set; }
public string Region { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Password { get; set; }
public string ConfirmPassword { get; set; }
}
public async Task<bool> RegisterAsync (string email, string password, string confirmPassword, string firstName, string lastName, string region)
{
var client = new HttpClient();
// create object to send to web api for registering
var model = new RegisterBindingModel
{
Email = email,
Password = password,
ConfirmPassword = confirmPassword,
FirstName = firstName,
LastName = lastName,
Region = region
};
var json = JsonConvert.SerializeObject(model);
HttpContent content = new StringContent(json);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
// add for API Key
content.Headers.Add(AppConstants.API_KEY_NAME, AppConstants.API_KEY_VALUE);
var response = await client.PostAsync(AppConstants.AZURE_WEB_API_REGISTER_URL, content);
return response.IsSuccessStatusCode;
}
a cursory glance at the docs for UserManager shows a FindByNameAsync method
Thanks #Jason for the help. It was easy in the end. This is how I solved it:
[Route("Register")]
public async Task<IHttpActionResult> Register(RegisterBindingModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var user = new ApplicationUser() { UserName = model.Email, Email = model.Email, FirstName = model.FirstName, LastName = model.LastName, Region = model.Region };
var existingUser = await UserManager.FindByEmailAsync(user.Email);
if (existingUser == null)
{
IdentityResult result = await UserManager.CreateAsync(user, model.Password);
if (!result.Succeeded)
{
return GetErrorResult(result);
}
return Ok();
}
else
{
var errorModel = new
{
error = new
{
code = 400,
message = "Email already exists"
}
};
return Content(HttpStatusCode.BadRequest, errorModel);
}
}