How to import a Class from another py file? - python

I'm using an open source library. They added a new functionality which I want but I can not upgrade the library yet.
I downloaded the relevant .py file and refrence it in my code as:
Original:
from airflow.contrib.operators.bigquery_check_operator import BigQueryCheckOperator
New:
from /home/.../airflow/MyOperators/bigquery_check_operator.py import BigQueryCheckOperator as MyBigQueryCheckOperator
However this doesn't work. it gives an invalid syntax error.
Basically I want to reference this file as MyBigQueryCheckOperator while the original one remains BigQueryCheckOperator
What am I doing wrong?

This is invalid syntax. You can't use / or file extentions in a python import path.
from /home/.../airflow/MyOperators/bigquery_check_operator.py import BigQueryCheckOperator as MyBigQueryCheckOperator
You should move the file to a relative directory and import it using regular python import syntax.
from newversion.bigquery_check_operator import BigQueryCheckOperator as MyBigQueryCheckOperator

You can add the path of the package temporarily by appending the path of the package into sys.path. Try:
import sys
sys.path.append('/home/.../airflow/MyOperators/')
from bigquery_check_operator import BigQueryCheckOperator
instead.

public class Home extends AppCompatActivity {
EditText txt_name,txt_password;
Button btn_login,btn_register;
DBHelper dbHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
dbHelper=new DBHelper(this);
txt_name=(EditText)findViewById(R.id.txt_name);
txt_password=(EditText)findViewById(R.id.txt_password);
btn_login=(Button) findViewById(R.id.btn_login);
btn_register=(Button) findViewById(R.id.btn_register);
}
public void buttonClick(View view){
switch (view.getId()){
case R.id.btn_login:
List<User> userList=dbHelper.readAllInfo();
int id=0;
for (int i=0;i<userList.size();i++){
User user = userList.get(i);
if(user.getUserName().equals(txt_name.getText().toString()) && user.getPassword().equals(txt_password.getText().toString())){
id=user.getId();
}
}
if(id>0){
Toast.makeText(this,"Login Successful!!!",Toast.LENGTH_SHORT).show();
Intent intent = new Intent(this,EditProfile.class);
intent.putExtra("ID",id);
startActivity(intent);
this.finish();
break;
}
else
Toast.makeText(this,"Login Unsuccessful!!!",Toast.LENGTH_SHORT).show();
break;
case R.id.btn_register:
Intent intent = new Intent(this,ProfileManagement.class);
startActivity(intent);
break;
}
}
}
public final class UserProfile {
private UserProfile(){}
public static class Users implements BaseColumns{
public final static String TABLE_NAME="UserInfo";
public final static String COLUMN_NAME="userName";
public final static String COLUMN_PASSWORD="password";
public final static String COLUMN_DOB="dateOfBirth";
public final static String COLUMN_GENDER="gender";
}
}
public class User {
private int id;
private String userName;
private String password;
private String dob;
private String gender;
public User() {
}
public User(int id, String userName, String password, String dob, String gender) {
this.id = id;
this.userName = userName;
this.password = password;
this.dob = dob;
this.gender = gender;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getDob() {
return dob;
}
public void setDob(String dob) {
this.dob = dob;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
public class ProfileManagement extends AppCompatActivity {
EditText txt_name,txt_password,txt_date;
RadioGroup rb_group;
RadioButton rb_male,rb_female;
Button btn_update;
DBHelper dbHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile_management);
dbHelper=new DBHelper(this);
txt_name=(EditText)findViewById(R.id.txt_name);
txt_password=(EditText)findViewById(R.id.txt_password);
txt_date=(EditText)findViewById(R.id.txt_date);
rb_group=(RadioGroup)findViewById(R.id.rb_group);
rb_male=(RadioButton)findViewById(R.id.rb_male);
rb_female=(RadioButton)findViewById(R.id.rb_female);
btn_update=(Button) findViewById(R.id.btn_update);
}
public void PMbuttonClick(View view){
User user= new User();
user.setUserName(txt_name.getText().toString());
user.setPassword(txt_password.getText().toString());
user.setDob(txt_date.getText().toString());
if(rb_group.getCheckedRadioButtonId()==R.id.rb_male)
user.setGender("Male");
else
user.setGender("Female");
long newId=dbHelper.addInfo(user);
if(newId>0) {
Toast.makeText(this, "Successfully Added", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(this,Home.class);
startActivity(intent);
finish();
}
else
Toast.makeText(this,"Unsuccessful Insertion!!!",Toast.LENGTH_SHORT).show();
}
}
public class EditProfile extends AppCompatActivity {
EditText txt_name,txt_password,txt_date;
RadioButton rb_male,rb_female;
Button btn_edit,btn_delete,btn_search;
DBHelper dbHelper;
int id;
User user;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_profile);
Intent intent=getIntent();
id=intent.getIntExtra("ID",-1);
dbHelper=new DBHelper(this);
user=new User();
txt_name=(EditText)findViewById(R.id.txt_name);
txt_password=(EditText)findViewById(R.id.txt_password);
txt_date=(EditText)findViewById(R.id.txt_date);
rb_male=(RadioButton)findViewById(R.id.rb_male);
rb_female=(RadioButton)findViewById(R.id.rb_female);
btn_search=(Button) findViewById(R.id.btn_search);
btn_delete=(Button) findViewById(R.id.btn_delete);
btn_edit=(Button) findViewById(R.id.btn_edit);
}
public void EPbuttonClick(View view){
switch (view.getId()){
case R.id.btn_search:
user=dbHelper.readAllInfo(id);
txt_name.setText(user.getUserName());
txt_password.setText(user.getPassword());
txt_date.setText(user.getDob());
if(user.getGender().equals("Male"))
rb_male.setChecked(true);
else
rb_female.setChecked(true);
break;
case R.id.btn_delete:
if(dbHelper.deleteInfo(id)){
Toast.makeText(this,"Successfully Deleted",Toast.LENGTH_SHORT).show();
Intent intent = new Intent(this,Home.class);
startActivity(intent);
}
break;
case R.id.btn_edit:
user.setId(id);
user.setUserName(txt_name.getText().toString());
user.setPassword(txt_password.getText().toString());
user.setDob(txt_date.getText().toString());
if(rb_male.isChecked())
user.setGender("Male");
else
user.setGender("Female");
if(dbHelper.updateInfo(user))
Toast.makeText(this,"Successfully Updated",Toast.LENGTH_SHORT).show();
else
Toast.makeText(this,"Update Unsuccessful",Toast.LENGTH_SHORT).show();
break;
}
}
#Override
public void onBackPressed() {
super.onBackPressed();
Intent intent = new Intent(this,Home.class);
startActivity(intent);
}
}
public class DBHelper extends SQLiteOpenHelper {
public static final String DATABASE="user.db";
public DBHelper(Context context) {
super(context, DATABASE, null, 1);
}
#Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
String query="CREATE TABLE "+ UserProfile.Users.TABLE_NAME +" ( "+
UserProfile.Users._ID +" INTEGER PRIMARY KEY, "+
UserProfile.Users.COLUMN_NAME +" TEXT, "+
UserProfile.Users.COLUMN_PASSWORD +" TEXT, "+
UserProfile.Users.COLUMN_DOB +" TEXT, "+
UserProfile.Users.COLUMN_GENDER +" TEXT);";
sqLiteDatabase.execSQL(query);
}
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
sqLiteDatabase.execSQL("DROP TABLE IF EXISTS "+ UserProfile.Users.TABLE_NAME);
onCreate(sqLiteDatabase);
}
public long addInfo(User user){
SQLiteDatabase db=getWritableDatabase();
ContentValues values=new ContentValues();
values.put(UserProfile.Users.COLUMN_NAME,user.getUserName());
values.put(UserProfile.Users.COLUMN_PASSWORD,user.getPassword());
values.put(UserProfile.Users.COLUMN_DOB,user.getDob());
values.put(UserProfile.Users.COLUMN_GENDER,user.getGender());
long id=db.insert(UserProfile.Users.TABLE_NAME,null,values);
return id;
}
public boolean updateInfo(User user){
SQLiteDatabase db=getReadableDatabase();
ContentValues values=new ContentValues();
values.put(UserProfile.Users.COLUMN_NAME,user.getUserName());
values.put(UserProfile.Users.COLUMN_PASSWORD,user.getPassword());
values.put(UserProfile.Users.COLUMN_DOB,user.getDob());
values.put(UserProfile.Users.COLUMN_GENDER,user.getGender());
String selection= UserProfile.Users._ID+" = ?";
String[] selectionArgs={Integer.toString(user.getId())};
int count=db.update(UserProfile.Users.TABLE_NAME,values,selection,selectionArgs);
if (count>0)
return true;
else
return false;
}
public List<User> readAllInfo(){
SQLiteDatabase db=getReadableDatabase();
String[] projection={UserProfile.Users._ID,
UserProfile.Users.COLUMN_NAME,
UserProfile.Users.COLUMN_PASSWORD,
UserProfile.Users.COLUMN_DOB,
UserProfile.Users.COLUMN_GENDER};
String order= UserProfile.Users._ID+" ASC";
Cursor cursor = db.query(UserProfile.Users.TABLE_NAME,projection,null,null,null,null,order);
List<User> list = new ArrayList();
User user=new User();
while(cursor.moveToNext()){
user.setId(cursor.getInt(cursor.getColumnIndex(UserProfile.Users._ID)));
user.setUserName(cursor.getString(cursor.getColumnIndex(UserProfile.Users.COLUMN_NAME)));
user.setPassword(cursor.getString(cursor.getColumnIndex(UserProfile.Users.COLUMN_PASSWORD)));
user.setDob(cursor.getString(cursor.getColumnIndex(UserProfile.Users.COLUMN_DOB)));
user.setGender(cursor.getString(cursor.getColumnIndex(UserProfile.Users.COLUMN_GENDER)));
list.add(user);
}
return list;
}
public User readAllInfo(int id){
SQLiteDatabase db=getReadableDatabase();
String[] projection={UserProfile.Users._ID,
UserProfile.Users.COLUMN_NAME,
UserProfile.Users.COLUMN_PASSWORD,
UserProfile.Users.COLUMN_DOB,
UserProfile.Users.COLUMN_GENDER};
String selection= UserProfile.Users._ID+" = ?";
String[] selectionArgs={Integer.toString(id)};
String order= UserProfile.Users._ID+" ASC";
Cursor cursor = db.query(UserProfile.Users.TABLE_NAME,projection,selection,selectionArgs,null,null,order);
User user=new User();
while(cursor.moveToNext()){
user.setId(cursor.getInt(cursor.getColumnIndex(UserProfile.Users._ID)));
user.setUserName(cursor.getString(cursor.getColumnIndex(UserProfile.Users.COLUMN_NAME)));
user.setPassword(cursor.getString(cursor.getColumnIndex(UserProfile.Users.COLUMN_PASSWORD)));
user.setDob(cursor.getString(cursor.getColumnIndex(UserProfile.Users.COLUMN_DOB)));
user.setGender(cursor.getString(cursor.getColumnIndex(UserProfile.Users.COLUMN_GENDER)));
}
return user;
}
public boolean deleteInfo(int id){
SQLiteDatabase db=getReadableDatabase();
String selection= UserProfile.Users._ID+" = ?";
String[] selectionArgs={Integer.toString(id)};
int count=db.delete(UserProfile.Users.TABLE_NAME,selection,selectionArgs);
if(count>0)
return true;
else
return false;
}
}

public boolean deleteInfo(int id) {
SQLiteDatabase db=getReadableDatabase();
String selection= UserProfile.Users._ID+" = ?";
String[] selectionArgs={Integer.toString(id)};
int count=db.delete(UserProfile.Users.TABLE_NAME,selection,selectionArgs);
if(count>0)
return true;
else
return false;
}

Related

Django Channels equivalent code for javax.websocket

I am new to Django Channels. I am trying to replicate what is being done in this Java code using Django Channels. But I cannot figure out how to send the message JSON to the Angular frontend.
The frontend has a table that will get updated throught the websocket implementation. But the recieve method doesn't seem to replicate what the onMessage method was doing. Django Channels performs a successful handshake. But that's all that happens.
Java Code
#ServerEndpoint("/socket/order")
#ApplicationScoped
public class OrderSocket {
Set<Session> sessions = new HashSet<>();
#OnOpen
public void onOpen(Session session) {
LOG.debug("onOpen " + session.getId());
sessions.add(session);
}
#OnClose
public void onClose(Session session) {
LOG.debug("onClose " + session.getId());
sessions.remove(session);
}
#OnError
public void onError(Session session, Throwable throwable) {
LOG.debug("onError " + session.getId() + " left on error: " + throwable);
sessions.remove(session);
}
#OnMessage
public void onMessage(String message) {
LOG.debug("onMessage " + message);
broadcast(message);
}
public void broadcast(OrderDto orderDto) {
Jsonb jsonb = JsonbBuilder.create();
String jsonString = jsonb.toJson(orderDto);
broadcast(jsonString);
}
private void broadcast(String message) {
sessions.forEach(s -> {
LOG.debug("Message broadcasted: " + message);
s.getAsyncRemote().sendObject(message, result -> {
if (result.getException() != null) {
LOG.error("Unable to send message: " + result.getException());
}
});
});
}
}
Python Code
consumer.py
class OrderConsumer(WebsocketConsumer):
log = logging.getLogger('main')
def connect(self):
self.log.debug("onOpen")
self.accept()
def receive(self, text_data=None, bytes_data=None):
self.log.debug("onMessage " + text_data)
self.send(text_data="Message = " + text_data)
def disconnect(self, code):
self.log.debug("onClose")
return super().disconnect(code)
Typescript code
export class OrderWebSocketService {
private API_URL = environment.API_URL;
private SOCKET_URL = this.API_URL.replace(/http/gi, "ws");
myWebSocket: WebSocketSubject<Order> = webSocket(this.SOCKET_URL + 'socket/order/');
constructor(private snackBar: MatSnackBar) { }
public connect(): Observable<Order> {
return this.myWebSocket.asObservable().pipe(
map((obj) => obj),
catchError((error) => this.errorHandler(error))
);
}
public close(): void {
this.myWebSocket.complete();
}
errorHandler(e: any): Observable<any> {
this.showMessage('Something wrong happened with websocket!', true);
return EMPTY;
}
showMessage(msg: string, isError: boolean = false): void {
this.snackBar.open(msg, 'X', {
duration: 3000,
horizontalPosition: "right",
verticalPosition: "top",
panelClass: isError ? ['msg-error'] : ['msg-success']
});
}
}
Would appreciate any suggestions.

Can I write Nested function in c#? [duplicate]

I am creating a C# library with some reusable code and was trying to create a method inside a method. I have a method like this:
public static void Method1()
{
// Code
}
What I would like to do is this:
public static void Method1()
{
public static void Method2()
{
}
public static void Method3()
{
}
}
Then I could choose either Method1.Method2 or Method1.Method3. Obviously the compiler isn't happy about this, any help is much appreciated. Thanks.
If by nested method, you mean a method that is only callable within that method (like in Delphi) you could use delegates.
public static void Method1()
{
var method2 = new Action(() => { /* action body */ } );
var method3 = new Action(() => { /* action body */ } );
//call them like normal methods
method2();
method3();
//if you want an argument
var actionWithArgument = new Action<int>(i => { Console.WriteLine(i); });
actionWithArgument(5);
//if you want to return something
var function = new Func<int, int>(i => { return i++; });
int test = function(6);
}
Yes, when C# 7.0 is released, Local Functions will allow you to do that. You will be able to have a method, inside a method as:
public int GetName(int userId)
{
int GetFamilyName(int id)
{
return User.FamilyName;
}
string firstName = User.FirstName;
var fullName = firstName + GetFamilyName(userId);
return fullName;
}
Note that public (and similar modifiers) are not supported C# programming guide:
Because all local functions are private, including an access modifier, such as the private keyword, generates compiler error CS0106, "
This answer was written before C# 7 came out. With C# 7 you can write local methods.
No, you can't do that. You could create a nested class:
public class ContainingClass
{
public static class NestedClass
{
public static void Method2()
{
}
public static void Method3()
{
}
}
}
You'd then call:
ContainingClass.NestedClass.Method2();
or
ContainingClass.NestedClass.Method3();
I wouldn't recommend this though. Usually it's a bad idea to have public nested types.
Can you tell us more about what you're trying to achieve? There may well be a better approach.
You can define delegates within your method with complete code and call them if you want.
public class MyMethods
{
public void Method1()
{
// defining your methods
Action method1 = new Action( () =>
{
Console.WriteLine("I am method 1");
Thread.Sleep(100);
var b = 3.14;
Console.WriteLine(b);
}
);
Action<int> method2 = new Action<int>( a =>
{
Console.WriteLine("I am method 2");
Console.WriteLine(a);
}
);
Func<int, bool> method3 = new Func<int, bool>( a =>
{
Console.WriteLine("I am a function");
return a > 10;
}
);
// calling your methods
method1.Invoke();
method2.Invoke(10);
method3.Invoke(5);
}
}
There is always an alternative of using a nested class within a class that will not be visible from outside and calling its methods, like:
public class SuperClass
{
internal static class HelperClass
{
internal static void Method2() {}
}
public void Method1 ()
{
HelperClass.Method2();
}
}
As of C# 7.0 you can do that:
public static void SlimShady()
{
void Hi([CallerMemberName] string name = null)
{
Console.WriteLine($"Hi! My name is {name}");
}
Hi();
}
This is called local functions, that is just what you were looking for.
I took the example from here, but further informatin can be found here and here.
Why you don't use classes?
public static class Helper
{
public static string MethodA()
{
return "A";
}
public static string MethodA()
{
return "A";
}
}
Now you can acces MethodA via
Helper.MethodA();
Older thread, but C# does have the concept of nested functions
Func<int> getCalcFunction(int total, bool useAddition)
{
int overallValue = 0;
if (useAddition)
{
Func<int> incrementer = new Func<int>(() =>
{
overallValue += total;
return overallValue;
});
return incrementer;
}
else
{
Func<int> decrementer = new Func<int>(() =>
{
overallValue -= total;
return overallValue;
});
return decrementer;
}
}
private void CalcTotals()
{
Func<int> decrem = getCalcFunction(30, false);
int a = decrem(); //result = -30
a = decrem(); //result = -60
Func<int> increm = getCalcFunction(30, true);
int b = increm(); //result = 30
b = increm(); //result = 60
}
Your nearly there
public static void Method1()
should be
public static class Method1{}
Don't you want to use nested class instead?
That's said, you seem to not respect the Single Responsibility Principle because you want a single method do more than one thing at a time.
Why don't you just Run a method within another
public void M1()
{
DO STUFF
}
public void M1()
{
DO STUFF
M1();
}

API data always null python-request post

I am calling an api and trying to post data to it but the data is always null. The api is expeting List<KeyValuePair<string,string>>. Here is the api call and the sample code from api.
API Call (Python)
import requests
data= {'CRHandle': 'Handle',
'UpdateParam':[{'Key':'Value'},{'Key1':'Value'}]}
resp_out = requests.post("http://localhost:56011/api/values/TestData",data = data)
print(resp_out.status_code)
data_out = resp_out.text
API Method (.NET)
[HttpPost]
public string TestData([FromBody] TicketUpdateModel updateData)
{
return JsonConvert.SerializeObject(updateData);
}
Data Model
public class TicketUpdateModel
{
public string CRHandle { get; set; }
public List<KeyValuePair<string, string>> UpdateParam { get; set; }
}
Data received at API end
What am I doing wrong?
Here is a sample program I tried. See if this helps.
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
var tm = new TicketUpdateModel() {
CRHandle = "blah",
UpdateParam = new List<KeyValuePair<string, string>>() {
new KeyValuePair<string, string>("Hello1", "WOrld1"),
new KeyValuePair<string, string>("Hello2", "WOrld2"),
}
};
var json = JsonConvert.SerializeObject(tm);
// prints {"CRHandle":"blah","UpdateParam":[{"Key":"Hello1","Value":"WOrld1"},{"Key":"Hello2","Value":"WOrld2"}]}
Console.WriteLine(json);
var tmd = JsonConvert.DeserializeObject<TicketUpdateModel>(json);
Console.WriteLine(tmd.CRHandle);
Console.WriteLine(tmd.UpdateParam[0].Key);
Console.WriteLine(tmd.UpdateParam[1].Value);
return;
}
}
public class TicketUpdateModel
{
public string CRHandle { get; set; }
public List<KeyValuePair<string, string>> UpdateParam { get; set; }
}

Android TCP client can't send data to server

I'm doing project with beacon.
smartphone(android client) collect rssi nearby beacons and send to python(server)
< current application's function >
-> when new beacon signal captured, display beacon's rssi value, Mac address
-> connect with tcp and send to python server in real time (Problem!!)
when using method(send text message to python server) with buttonclickevent,
connecting and sending text message works well.
but when i use method with listview adapter(using ArrayMap),
connecting works well, but can't send rssi.
more detail, infinite loop for waiting data
I think there is a problem between using runOnUiThread and data sending but i'm not sure about it.
Mainactivity
package midascon.example.scanlist;
import com.hanvitsi.midascon.Beacon;
import com.hanvitsi.midascon.BeaconCallback;
import com.hanvitsi.midascon.MidasApplication;
import com.hanvitsi.midascon.manager.ContextManager;
import android.Manifest;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.StrictMode;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.widget.ListView;
public class MainActivity extends Activity implements BeaconCallback, Runnable
{
private static final int MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 100;
private ContextManager contextManager;
private BeaconListAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (android.os.Build.VERSION.SDK_INT > 9) { StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); }
checkPermission();
contextManager = getMidasApplication().getContextManager();
contextManager.getBeaconSettings().setMidasScanMode(false);
adapter = new BeaconListAdapter(getBaseContext()); // Beacon list adapter
ListView listView = (ListView) findViewById(R.id.listView);
listView.setAdapter(adapter);
}
#Override
public void onBeaconCallback(int status, Beacon beacon) // add beacon to list when beacon signal captured
{
switch (status) {
case STATUS_CODE_ENTER:
case STATUS_CODE_UPDATE:
if (adapter != null)
adapter.addBeacon(beacon);
break;
case STATUS_CODE_EXIT:
if (adapter != null)
adapter.removeBeacon(beacon);
break;
default:
break;
}
runOnUiThread(this);
}
public void checkPermission() // allow permission
{
if(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
}
}
#Override
public void run() {
if (adapter != null)
adapter.notifyDataSetChanged();
}
// call name class setting by AndroidManifest.xml
public MidasApplication getMidasApplication() {
return (MidasApplication) getApplication();
}
#Override
protected void onResume() {
super.onResume();
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.ACCESS_FINE_LOCATION }, MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
}
else
{
ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.ACCESS_FINE_LOCATION }, MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
}
}
else {
if (BluetoothAdapter.getDefaultAdapter().isEnabled()) {
// register callback
contextManager.setBeaconCallback(this);
contextManager.startLeScan();
} else {
contextManager.stopLeScan();
Intent settingsIntent = new Intent(android.provider.Settings.ACTION_BLUETOOTH_SETTINGS);
startActivity(settingsIntent);
}
}
}
#Override
protected void onPause() {
super.onPause();
contextManager.stopLeScan();
}
}
midas is company that made beacon
BeaconListAdapter
public class BeaconListAdapter extends BaseAdapter
{
private final LayoutInflater inflater;
private int count; //counting beacon
private final ArrayMap<String, Beacon> itemMap = new ArrayMap<String, Beacon>();
private final int padding;
public int CurBeaconHave = 2;
private Handler mHandler;
public int port = 9999;
public int initcnt = 0;
public int stackcnt = 0;
public int serveractivate = 0;
public int praccnt = 0;
public static String Sendrssi = "";
public Socket socket = null;
public BeaconListAdapter(Context context) {
super();
padding = (int) context.getResources().getDimension(R.dimen.activity_vertical_margin);
this.inflater = LayoutInflater.from(context);
}
public int addBeacon(Beacon beacon) {
synchronized (itemMap) {
itemMap.put(beacon.getMac(), beacon);
count = itemMap.size();
return count;
}
}
public int removeBeacon(Beacon beacon) {
synchronized (itemMap) {
itemMap.remove(beacon.getMac());
count = itemMap.size();
return count;
}
}
#Override
public int getCount() {
return count;
}
#Override
public Beacon getItem(int position) {
synchronized (itemMap) {
return itemMap.valueAt(position);
}
}
void ToPython() {
try {
String tmp = Sendrssi;
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));
out.println(tmp);
out.flush();
Log.d("sendrssi ",tmp);
}
catch (Exception e) {
e.printStackTrace();
}
}
/*public void ToPython() {
try {
String tmp = Sendrssi;
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
out.write(tmp);
out.newLine();
out.flush();
Log.d("Sending. Rssi : ", tmp);
} catch (Exception e) {
e.printStackTrace();
}
}*/
void connect() {
Log.w("state", "connecting..");
Thread checkUpdate = new Thread() {
public void run() {
String newip = "192.168.0.4";
try {
socket = new Socket(newip, port);
Log.w("state ", "server connected");
serveractivate = 1;
} catch (IOException e1) {
Log.w("state ", "failed");
e1.printStackTrace();
System.out.println("error :" + e1.getMessage());
}
}
};
checkUpdate.start();
}
#Override
public long getItemId(int position) {
return position;
}
public void stopsocket()
{
try
{
socket.close();
} catch (IOException e){
e.printStackTrace();
}
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView textView = null;
if (convertView == null)
{
convertView = inflater.inflate(android.R.layout.simple_list_item_1, parent, false);
textView = (TextView) convertView.findViewById(android.R.id.text1);
textView.setBackgroundColor(Color.WHITE);
textView.setTextColor(Color.BLACK);
textView.setPadding(padding, padding, padding, padding);
convertView.setTag(textView);
}
else
{
textView = (TextView) convertView.getTag();
}
Beacon item = getItem(position);
int temprssi = item.getRssi();
while(serveractivate == 0)
{
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d("Connect State : ","wait for Server Connect...");
connect();
}
if(serveractivate == 1)
{
try {
socket.setTcpNoDelay(true);
} catch (SocketException e) {
e.printStackTrace();
}
}
int[] values = BeaconUtils.getAccelerometer(item);
textView.setText(String.format("[%s]\nMAC : %s\nRssi : %d\n", item.getType() == Beacon.TYPE_MIDAS ? "Midascon" : "Beacon", item.getMac(),temprssi));
if(count == CurBeaconHave)
{
if(stackcnt == CurBeaconHave)
{
ToPython();
stackcnt = 0;
Sendrssi = "";
}
else if(stackcnt != CurBeaconHave)
{
Sendrssi = Sendrssi + temprssi + " " ;//+ (temprssi - 3) + " " + (temprssi + 5) + " " + (temprssi - 7) + " ";
stackcnt++;
}
}
return convertView;
}
}
total code line is about 400 line, so i upload code that have problem i think.
thank you for reading and try to solve my problem
if you need another code i'll upload it
Note that i'm not good at english, so you may have difficult with reading and understand. sorry for that :(
problem solved.
It's not a normal method, so please be patient.
BeaconListadapter in connect method, i use thread.
but i don't use thread in Topython method.
because of this, there's problem with socket information when send data
so i delete thread in connect method and run and method
in main thread(i know this is idiot thing)
if you use like me, probably use connect and send data method in one thread

How to send the "token" as a header from a GUI application to at GET command in a flask service? [duplicate]

I have an HttpClient that I am using for a REST API. However I am having trouble setting up the Authorization header. I need to set the header to the token I received from doing my OAuth request.
I saw some code for .NET that suggests the following,
httpClient.DefaultRequestHeaders.Authorization = new Credential(OAuth.token);
However the Credential class does that not exist in WinRT. Anyone have any ideas how to set the Authorization header?
So the way to do it is the following,
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "Your Oauth token");
request.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue(
"Basic", Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes(
$"{yourusername}:{yourpwd}")));
I look for a good way to deal with this issue and I am looking at the same question. Hopefully, this answer will be helping everyone who has the same problem likes me.
using (var client = new HttpClient())
{
var url = "https://www.theidentityhub.com/{tenant}/api/identity/v1";
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
var response = await client.GetStringAsync(url);
// Parse JSON response.
....
}
reference from https://www.theidentityhub.com/hub/Documentation/CallTheIdentityHubApi
As it is a good practice to reuse the HttpClient instance, for performance and port exhaustion problems, and because none of the answers give this solution (and even leading you toward bad practices :( ), I put here a link towards the answer I made on a similar question :
https://stackoverflow.com/a/40707446/717372
Some sources on how to use HttpClient the right way:
https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/
https://blogs.msdn.microsoft.com/alazarev/2017/12/29/disposable-finalizers-and-httpclient/
I suggest to you:
HttpClient.DefaultRequestHeaders.Add("Authorization", "Bearer <token>");
And then you can use it like that:
var response = await client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
responseMessage = await response.Content.ReadAsAsync<ResponseMessage>();
}
In the case you want to send HttpClient request with Bearer Token, this code can be a good solution:
var requestMessage = new HttpRequestMessage
{
Method = HttpMethod.Post,
Content = new StringContent(".....", Encoding.UTF8, "application/json"),
RequestUri = new Uri(".....")
};
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "Your token");
var response = await _httpClient.SendAsync(requestMessage);
I was setting the bearer token
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
It was working in one endpoint, but not another. The issue was that I had lower case b on "bearer". After change now it works for both api's I'm hitting. Such an easy thing to miss if you aren't even considering it as one of the haystacks to look in for the needle.
Make sure to have "Bearer" - with capital.
Use Basic Authorization And Json Parameters.
using (HttpClient client = new HttpClient())
{
var request_json = "your json string";
var content = new StringContent(request_json, Encoding.UTF8, "application/json");
var authenticationBytes = Encoding.ASCII.GetBytes("YourUsername:YourPassword");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(authenticationBytes));
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var result = await client.PostAsync("YourURL", content);
var result_string = await result.Content.ReadAsStringAsync();
}
For anyone finding this old thread now (2021), please look at this documentation about HttpClientFactory which is injectable and will also re-run on each request avoiding expired tokens which will make it useful for bearer tokens, generated clients, pooling etc.
TL;DR: Use HttpClientFactory and a DelegatingHandler which will act as middleware on all outgoing requests with your configured client.
This is how I add my bearer for Azure Identity (managed by Azure) but you can get the token however you want of course;
using Microsoft.Azure.Services.AppAuthentication;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
public class BearerTokenHandler : DelegatingHandler
{
public BearerTokenHandler(AzureServiceTokenProvider tokenProvider, string resource)
{
TokenProvider = tokenProvider;
Resource = resource;
}
public AzureServiceTokenProvider TokenProvider { get; }
public string Resource { get; }
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (!request.Headers.Contains("Authorization"))
{
// Fetch your token here
string token = await TokenProvider.GetAccessTokenAsync(Resource);
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
}
return await base.SendAsync(request, cancellationToken);
}
}
I configure my typed clients (generated with NSwag) like this in Startup;
var accessTokenProvider = new AzureServiceTokenProvider("<your-connection-string-for-access-token-provider>");
builder.Services.AddHttpClient<IOrdersClient, OrdersClient>().ConfigureHttpClient(async conf =>
{
conf.BaseAddress = new Uri("<your-api-base-url>");
}).AddHttpMessageHandler(() => new BearerTokenHandler(accessTokenProvider, "https://your-azure-tenant.onmicrosoft.com/api"));
Then you can inject your IOrdersClient wherever you like and all requests will have the bearer.
If you want to reuse the HttpClient, it is advised to not use the DefaultRequestHeaders as they are used to send with each request.
You could try this:
var requestMessage = new HttpRequestMessage
{
Method = HttpMethod.Post,
Content = new StringContent("...", Encoding.UTF8, "application/json"),
RequestUri = new Uri("...")
};
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes($"{user}:{password}")));
var response = await _httpClient.SendAsync(requestMessage);
To set basic authentication with C# HttpClient. The following code is working for me.
using (var client = new HttpClient())
{
var webUrl ="http://localhost/saleapi/api/";
var uri = "api/sales";
client.BaseAddress = new Uri(webUrl);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.ConnectionClose = true;
//Set Basic Auth
var user = "username";
var password = "password";
var base64String =Convert.ToBase64String( Encoding.ASCII.GetBytes($"{user}:{password}"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",base64String);
var result = await client.PostAsJsonAsync(uri, model);
return result;
}
This is how i have done it:
using (HttpClient httpClient = new HttpClient())
{
Dictionary<string, string> tokenDetails = null;
var messageDetails = new Message { Id = 4, Message1 = des };
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:3774/");
var login = new Dictionary<string, string>
{
{"grant_type", "password"},
{"username", "sa#role.com"},
{"password", "lopzwsx#23"},
};
var response = client.PostAsync("Token", new FormUrlEncodedContent(login)).Result;
if (response.IsSuccessStatusCode)
{
tokenDetails = JsonConvert.DeserializeObject<Dictionary<string, string>>(response.Content.ReadAsStringAsync().Result);
if (tokenDetails != null && tokenDetails.Any())
{
var tokenNo = tokenDetails.FirstOrDefault().Value;
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + tokenNo);
client.PostAsJsonAsync("api/menu", messageDetails)
.ContinueWith((postTask) => postTask.Result.EnsureSuccessStatusCode());
}
}
}
This you-tube video help me out a lot. Please check it out.
https://www.youtube.com/watch?v=qCwnU06NV5Q
6 Years later but adding this in case it helps someone.
https://www.codeproject.com/Tips/996401/Authenticate-WebAPIs-with-Basic-and-Windows-Authen
var authenticationBytes = Encoding.ASCII.GetBytes("<username>:<password>");
using (HttpClient confClient = new HttpClient())
{
confClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(authenticationBytes));
confClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(Constants.MediaType));
HttpResponseMessage message = confClient.GetAsync("<service URI>").Result;
if (message.IsSuccessStatusCode)
{
var inter = message.Content.ReadAsStringAsync();
List<string> result = JsonConvert.DeserializeObject<List<string>>(inter.Result);
}
}
UTF8 Option
request.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue(
"Basic", Convert.ToBase64String(
System.Text.Encoding.UTF8.GetBytes(
$"{yourusername}:{yourpwd}")));
Using AuthenticationHeaderValue class of System.Net.Http assembly
public AuthenticationHeaderValue(
string scheme,
string parameter
)
we can set or update existing Authorization header for our httpclient like so:
httpclient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", TokenResponse.AccessToken);
BaseWebApi.cs
public abstract class BaseWebApi
{
//Inject HttpClient from Ninject
private readonly HttpClient _httpClient;
public BaseWebApi(HttpClient httpclient)
{
_httpClient = httpClient;
}
public async Task<TOut> PostAsync<TOut>(string method, object param, Dictionary<string, string> headers, HttpMethod httpMethod)
{
//Set url
HttpResponseMessage response;
using (var request = new HttpRequestMessage(httpMethod, url))
{
AddBody(param, request);
AddHeaders(request, headers);
response = await _httpClient.SendAsync(request, cancellationToken);
}
if(response.IsSuccessStatusCode)
{
return await response.Content.ReadAsAsync<TOut>();
}
//Exception handling
}
private void AddHeaders(HttpRequestMessage request, Dictionary<string, string> headers)
{
request.Headers.Accept.Clear();
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
if (headers == null) return;
foreach (var header in headers)
{
request.Headers.Add(header.Key, header.Value);
}
}
private static void AddBody(object param, HttpRequestMessage request)
{
if (param != null)
{
var content = JsonConvert.SerializeObject(param);
request.Content = new StringContent(content);
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
}
}
SubWebApi.cs
public sealed class SubWebApi : BaseWebApi
{
public SubWebApi(HttpClient httpClient) : base(httpClient) {}
public async Task<StuffResponse> GetStuffAsync(int cvr)
{
var method = "get/stuff";
var request = new StuffRequest
{
query = "GiveMeStuff"
}
return await PostAsync<StuffResponse>(method, request, GetHeaders(), HttpMethod.Post);
}
private Dictionary<string, string> GetHeaders()
{
var headers = new Dictionary<string, string>();
var basicAuth = GetBasicAuth();
headers.Add("Authorization", basicAuth);
return headers;
}
private string GetBasicAuth()
{
var byteArray = Encoding.ASCII.GetBytes($"{SystemSettings.Username}:{SystemSettings.Password}");
var authString = Convert.ToBase64String(byteArray);
return $"Basic {authString}";
}
}
In net .core you can use with Identity Server 4
var client = new HttpClient();
client.SetBasicAuthentication(userName, password);
or
var client = new HttpClient();
client.SetBearerToken(token);
see https://github.com/IdentityModel/IdentityModel/blob/main/src/Client/Extensions/AuthorizationHeaderExtensions.cs
this could works, if you are receiving a json or an xml from the service and i think this can give you an idea about how the headers and the T type works too, if you use the function MakeXmlRequest(put results in xmldocumnet) and MakeJsonRequest(put the json in the class you wish that have the same structure that the json response) in the next way
/*-------------------------example of use-------------*/
MakeXmlRequest<XmlDocument>("your_uri",result=>your_xmlDocument_variable = result,error=>your_exception_Var = error);
MakeJsonRequest<classwhateveryouwant>("your_uri",result=>your_classwhateveryouwant_variable=result,error=>your_exception_Var=error)
/*-------------------------------------------------------------------------------*/
public class RestService
{
public void MakeXmlRequest<T>(string uri, Action<XmlDocument> successAction, Action<Exception> errorAction)
{
XmlDocument XMLResponse = new XmlDocument();
string wufooAPIKey = ""; /*or username as well*/
string password = "";
StringBuilder url = new StringBuilder();
url.Append(uri);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url.ToString());
string authInfo = wufooAPIKey + ":" + password;
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
request.Timeout = 30000;
request.KeepAlive = false;
request.Headers["Authorization"] = "Basic " + authInfo;
string documento = "";
MakeRequest(request,response=> documento = response,
(error) =>
{
if (errorAction != null)
{
errorAction(error);
}
}
);
XMLResponse.LoadXml(documento);
successAction(XMLResponse);
}
public void MakeJsonRequest<T>(string uri, Action<T> successAction, Action<Exception> errorAction)
{
string wufooAPIKey = "";
string password = "";
StringBuilder url = new StringBuilder();
url.Append(uri);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url.ToString());
string authInfo = wufooAPIKey + ":" + password;
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
request.Timeout = 30000;
request.KeepAlive = false;
request.Headers["Authorization"] = "Basic " + authInfo;
// request.Accept = "application/json";
// request.Method = "GET";
MakeRequest(
request,
(response) =>
{
if (successAction != null)
{
T toReturn;
try
{
toReturn = Deserialize<T>(response);
}
catch (Exception ex)
{
errorAction(ex);
return;
}
successAction(toReturn);
}
},
(error) =>
{
if (errorAction != null)
{
errorAction(error);
}
}
);
}
private void MakeRequest(HttpWebRequest request, Action<string> successAction, Action<Exception> errorAction)
{
try{
using (var webResponse = (HttpWebResponse)request.GetResponse())
{
using (var reader = new StreamReader(webResponse.GetResponseStream()))
{
var objText = reader.ReadToEnd();
successAction(objText);
}
}
}catch(HttpException ex){
errorAction(ex);
}
}
private T Deserialize<T>(string responseBody)
{
try
{
var toReturns = JsonConvert.DeserializeObject<T>(responseBody);
return toReturns;
}
catch (Exception ex)
{
string errores;
errores = ex.Message;
}
var toReturn = JsonConvert.DeserializeObject<T>(responseBody);
return toReturn;
}
}
}
It may be easier to use an existing library.
For example, the extension methods below are added with Identity Server 4
https://www.nuget.org/packages/IdentityModel/
public static void SetBasicAuthentication(this HttpClient client, string userName, string password);
//
// Summary:
// Sets a basic authentication header.
//
// Parameters:
// request:
// The HTTP request message.
//
// userName:
// Name of the user.
//
// password:
// The password.
public static void SetBasicAuthentication(this HttpRequestMessage request, string userName, string password);
//
// Summary:
// Sets a basic authentication header for RFC6749 client authentication.
//
// Parameters:
// client:
// The client.
//
// userName:
// Name of the user.
//
// password:
// The password.
public static void SetBasicAuthenticationOAuth(this HttpClient client, string userName, string password);
//
// Summary:
// Sets a basic authentication header for RFC6749 client authentication.
//
// Parameters:
// request:
// The HTTP request message.
//
// userName:
// Name of the user.
//
// password:
// The password.
public static void SetBasicAuthenticationOAuth(this HttpRequestMessage request, string userName, string password);
//
// Summary:
// Sets an authorization header with a bearer token.
//
// Parameters:
// client:
// The client.
//
// token:
// The token.
public static void SetBearerToken(this HttpClient client, string token);
//
// Summary:
// Sets an authorization header with a bearer token.
//
// Parameters:
// request:
// The HTTP request message.
//
// token:
// The token.
public static void SetBearerToken(this HttpRequestMessage request, string token);
//
// Summary:
// Sets an authorization header with a given scheme and value.
//
// Parameters:
// client:
// The client.
//
// scheme:
// The scheme.
//
// token:
// The token.
public static void SetToken(this HttpClient client, string scheme, string token);
//
// Summary:
// Sets an authorization header with a given scheme and value.
//
// Parameters:
// request:
// The HTTP request message.
//
// scheme:
// The scheme.
//
// token:
// The token.
public static void SetToken(this HttpRequestMessage request, string scheme, string token);
Firstly, I wouldn't use HttpClient directly. It's too easy to make mistakes - particularly in the area of headers. The DefaultHeadersCollection is not immutable and not thread-safe because other parts of the app can change the headers on you. It's best to set the headers when you make the call. If you are working with an abstraction, and that is recommended because the classes in this area are a bit of a mess, you would want to have a headers collection and put those on your HttpRequestMessage before you send it. You need to make sure you put the content headers on the content, and not the message.
Code Reference
foreach (var headerName in request.Headers.Names)
{
//"Content-Type"
if (string.Compare(headerName, HeadersExtensions.ContentTypeHeaderName, StringComparison.OrdinalIgnoreCase) == 0)
{
//Note: not sure why this is necessary...
//The HttpClient class seems to differentiate between content headers and request message headers, but this distinction doesn't exist in the real world...
//TODO: Other Content headers
httpContent?.Headers.Add(HeadersExtensions.ContentTypeHeaderName, request.Headers[headerName]);
}
else
{
httpRequestMessage.Headers.Add(headerName, request.Headers[headerName]);
}
}
Here is a data structure that you could use to send the request which includes the headers.
Code Reference
public interface IRequest
{
CancellationToken CancellationToken { get; }
string? CustomHttpRequestMethod { get; }
IHeadersCollection Headers { get; }
HttpRequestMethod HttpRequestMethod { get; }
AbsoluteUrl Uri { get; }
}
public interface IRequest<TBody> : IRequest
{
TBody? BodyData { get; }
}
And, a headers collection:
Code Reference
public sealed class HeadersCollection : IHeadersCollection
{
#region Fields
private readonly IDictionary<string, IEnumerable<string>> dictionary;
#endregion
#region Public Constructors
public HeadersCollection(IDictionary<string, IEnumerable<string>> dictionary) => this.dictionary = dictionary;
public HeadersCollection(string key, string value) : this(ImmutableDictionary.CreateRange(
new List<KeyValuePair<string, IEnumerable<string>>>
{
new(key, ImmutableList.Create(value))
}
))
{
}
#endregion Public Constructors
#region Public Properties
public static HeadersCollection Empty { get; } = new HeadersCollection(ImmutableDictionary.Create<string, IEnumerable<string>>());
public IEnumerable<string> Names => dictionary.Keys;
IEnumerable<string> IHeadersCollection.this[string name] => dictionary[name];
#endregion Public Properties
#region Public Methods
public bool Contains(string name) => dictionary.ContainsKey(name);
public IEnumerator<KeyValuePair<string, IEnumerable<string>>> GetEnumerator() => dictionary.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => dictionary.GetEnumerator();
public override string ToString() => string.Join("\r\n", dictionary.Select(kvp => $"{kvp.Key}: {string.Join(", ", kvp.Value)}\r\n"));
#endregion
}
See all the working code and examples here.
You can too to use the follow exemple, that it use IHttpClientFactory:
readonly IHttpClientFactory _httpClientFactory;
public HTTPClientHelper(IHttpClientFactory httpClientFactory, string clientName = null)
{
this._httpClientFactory = httpClientFactory;
}
public Task<T> GetAsync(string url, string token) {
var client = _httpClientFactory.CreateClient(_clientName);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(JwtBearerDefaults.AuthenticationScheme, token);
using (HttpResponseMessage response = await _client.GetAsync(url)){
......
}
}
I came across this old thread. The problem I had was that I know to use a static HttpClient, but my token needs refreshing every 59 minutes.
So I could have used HttpClientFactory, but because one of my projects was still in .NET 4.8, I created a class that inherited from HttpClient so I have similar code in all projects. A secret is needed to be able to get the token (I'm using identityserver4).
I then set that as a singleton in DI (I'm using Ninject here):
Bind<MyHttpClient>().ToMethod(c =>
{
var accessKey = ConfigurationManager.AppSettings["AccessKey"];
var client = new MyHttpClient(accessKey)
{
BaseAddress = new Uri(MyUrls.MyApiBaseUrl)
};
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
return client;
}).InSingletonScope();
Then the class itself - named after the API it is used to access:
public class MyHttpClient : BaseHttpClient
{
private static readonly HttpClient _authHttpClient = new HttpClient();
private string _secret;
public MyHttpClient(string secret)
{
_secret = secret;
}
/// <summary>
/// Add the token to each and every request, cached for 1 minute less than the token's lifetime
/// </summary>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var cacheSeconds = 3600 - 60; // Default of 59 minutes
var token = CacheHelper<string>.Get("MyToken", cacheSeconds * 60, () =>
{
var authorityUrl = MyUrls.AuthServerUrl;
// discover endpoints from metadata
DiscoveryDocumentResponse disco;
disco = _authHttpClient.GetDiscoveryDocumentAsync(authorityUrl).Result;
if (disco.IsError)
{
throw new Exception("Error getting discovery document: " + disco.Error);
}
// request token
var tokenResponse = _authHttpClient.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "myapp",
ClientSecret = _secret,
Scope = "myapi"
}).Result;
if (tokenResponse.IsError)
{
throw new Exception("Error getting token: " + tokenResponse.Error);
}
if (tokenResponse.ExpiresIn < cacheSeconds + 60)
{
throw new Exception($"Token expires in {tokenResponse.ExpiresIn}s, which is less than {cacheSeconds + 60}");
}
if (tokenResponse.ExpiresIn > cacheSeconds + 60)
{
Log.Warn().Message($"Token expiry in {tokenResponse.ExpiresIn}s, which is greater than {cacheSeconds}").Write();
}
return tokenResponse.AccessToken;
});
// THIS IS THE BIT - Assign this inside a SendAsync override and you are done!
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
return base.SendAsync(request, cancellationToken);
}
}
Finally just for completeness, my CacheHelper class looks like this:
public static class CacheHelper<T>
{
private static readonly object _locker = new object();
public static T Get(string cacheName, int cacheTimeoutSeconds, Func<T> func)
{
var obj = MemoryCache.Default.Get(cacheName, null);
if (obj != null) return (T)obj;
lock (_locker)
{
obj = MemoryCache.Default.Get(cacheName, null);
if (obj == null)
{
obj = func();
var cip = new CacheItemPolicy
{
AbsoluteExpiration = new DateTimeOffset(DateTime.UtcNow.AddSeconds(cacheTimeoutSeconds))
};
MemoryCache.Default.Set(cacheName, obj, cip);
}
}
return (T)obj;
}
}
Oauth Process flow is complex and there is always a room for one error or another.
My suggestion will be to always use the boilerplate code and a set of libraries for OAuth authentication flow.It will make your life easier.
Here is the link for the set of libraries.OAuth Libraries for .Net
If you are using Visual Studio IISExpress debug mode and connecting to the HTTP port rather than the HTTPS port you may find that the auth headers are being dropped.
Switch to the SLL connection and they will appear again.
unsure why, possibly the setup redirects the http traffic and that causes the auth to be removed.
This may help Setting the header:
WebClient client = new WebClient();
string authInfo = this.credentials.UserName + ":" + this.credentials.Password;
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
client.Headers["Authorization"] = "Basic " + authInfo;
static async Task<AccessToken> GetToken()
{
string clientId = "XXX";
string clientSecret = "YYY";
string credentials = String.Format("{0}:{1}", clientId, clientSecret);
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes(credentials)));
List<KeyValuePair<string, string>> requestData = new List<KeyValuePair<string, string>>();
requestData.Add(new KeyValuePair<string, string>("grant_type", "client_credentials"));
FormUrlEncodedContent requestBody = new FormUrlEncodedContent(requestData);
var request = await client.PostAsync("https://accounts.spotify.com/api/token", requestBody);
var response = await request.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<AccessToken>(response);
}
}

Categories