xamarin how to change the unique id of child in firebase - c#

I'm a beginner in firebase and i'm using nuget FirebaseDatabase.net.
I'm trying to replace the unique id of child with the users uid this is how it looks in the database
i tryed this code but it didnt work
private async void signupbutton_Clicked(object sender, EventArgs e)
{
// the registration part
FirebaseClient firebaseClient = new FirebaseClient("foo");
try
{
var authProvider = new FirebaseAuthProvider(new FirebaseConfig(webApiKey));
var auth = await authProvider.CreateUserWithEmailAndPasswordAsync(UserNewEmail.Text, UserNewPassword.Text);
string getToken = auth.FirebaseToken;
//save user info in database
await firebaseClient.Child("users").Child("some uid").PostAsync(new userinfo
{
firstName = UserFirstName.Text ,
secondName = UsersecondName.Text
}) ;
await App.Current.MainPage.DisplayAlert("Alert", auth.User.LocalId, "Ok");
}
catch (Exception ex)
{
await App.Current.MainPage.DisplayAlert("Alert", "ala " + ex.Message, "OK");
}
}
and this is the opject im trying to send
class userinfo
{
public string firstName { get; set; }
public string secondName { get; set; }
}
pleace let me know if my question needs more Clarificatio thanks in advance.

When you Post to Firebase Realtime Database it always creates a new child node with a generated unique ID. If you want to specify your own ID, specify the entire path you want to write to (including that ID) and then use Put.
// 👇 👇
await firebaseClient.Child("users").Child("some uid").child(getToken).PutAsync(new userinfo
{
firstName = UserFirstName.Text ,
secondName = UsersecondName.Text
}) ;

Related

C# Update Azure Cosmos Db json item with Upsert

I'm (new to CosmosDb) and trying to update an item in an Azure Cosmos db, but it's inserting instead.
The object sent is
public class Bank
{
public string id { get; set; }
public string Code { get; set; }
public string Name { get; set; }
}
I tried passing only the Code and the Name values back (i.e. I did not include the id in the object, which causes an insert (I wanted an update).
I am now including the id which results in an error.
Error returned is:
ResourceType Document is unexpected.
ActivityId: a0d50426-c556-4b17-9646-93052699026e, Windows/10.0.19044 documentdb-netcore-sdk/2.16.2
So, it's values after a front end update (only changing the Name value) are:
Code: "FNB"
Name: "aa First Update Test"
id: "d76ade3d-7d02-46e5-a458-e9f0781bf044"
The DAL code:
var documentUri = UriFactory.CreateDocumentUri(DBName, "Banks", bank.Code);
try
{
Document doc = await client.UpsertDocumentAsync(documentUri, bank);
}
How do I get it to update?
TIA
Your Code is not clear and dont have enough information.try these functions.
protected DataContext(string endpointUrl, string databaseId,
string masterKey)
{
_databaseId = databaseId;
_masterKey = masterKey;
_databaseUri = UriFactory.CreateDatabaseUri(_databaseId);
this._client = new DocumentClient(new Uri(endpointUrl), _masterKey);
this._client.CreateDatabaseIfNotExistsAsync(new Database
{ Id = _databaseId });
this._client.CreateDocumentCollectionIfNotExistsAsync(
UriFactory.CreateDatabaseUri(_databaseId),
new DocumentCollection { Id = CollectionId });
_databaseCollectionUri = UriFactory.CreateDocumentCollectionUri(
_databaseId, CollectionId);
}
insert and update using
public async Task<Document> UpsertDocumentAsync(T entity)
{
var result = await this._client.UpsertDocumentAsync(
_databaseCollectionUri, entity);
return result;
}
Or Try please using the nuget Microsoft.Azure.Cosmos;
string cosmosDbConnectionString = CosmosDbConnectionKey;
CosmosClient cosmosClient = new CosmosClient(cosmosDbConnectionString);
var db = CosmosDbNameKey;
var container = ContainerKey;
await container.UpsertItemAsync(Model, new PartitionKey(Model.PK));
What I needed was the DocumentCollection (DocumentCollection Link) in the Upsert, but I had the Document Link (documentUri)
So,
public async Task<ExBool> UpdateAsyncPOCO(Bank bank)
{
// NB: UpsertDocumentAsync should take the DocumentCollection link, instead of Document link.
// This is a DocumentLink
var documentUri = UriFactory.CreateDocumentUri(DBName, "Banks", bank.Code);
// This is a DocumentCollection
var CollectionUri = UriFactory.CreateDocumentCollectionUri("demo", "Banks");
try
{
Document doc = await client.UpsertDocumentAsync(CollectionUri, bank);
}
catch (Exception ex)
{
HandleException(ex);
}
return result;
}
Insert and update work perfectly now.
The model and values for the update:
Code: "updated FNB 2"
Name: "updated First National Bank 22"
id: "d76ade3d-7d02-46e5-a458-e9f0781bf044"
Similarly, the Insert
Code: "qwerty"
Name: "qwertyuiop"
id: ""

ASP.NET MVC 5 Identity - "A user name already exists" when using custom user

I am using ASP.NET MVC 5 to create a web app.
For the purposes of my app I have created a seprate "Website User" class that looks like this:
public class WebsiteUser
{
public WebsiteUser()
{
this.Comments = new List<CommentEntityModel>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ApplicationUser IdentityUser { get; set; }
public ICollection<CommentEntityModel> Comments { get; set; }
}
My issue comes when I try and register a new user into the website.
My register action looks like this
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Username, Email = model.Email };
var websiteUser = service.CreateWebsiteUser(user);
var result = await UserManager.CreateAsync(user, model.Password);
var websiteUserResult = service.RegisterWebsiteUser(websiteUser);
UserManager.AddToRole(user.Id, UserRoles.WebsiteUser.ToString());
if (result.Succeeded && websiteUserResult)
{
await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);
return RedirectToAction("Index", "Home");
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
Pretty much the default one that Identity creates, except for these two lines:
var websiteUser = service.CreateWebsiteUser(user);
var websiteUserResult = service.RegisterWebsiteUser(websiteUser);
And what I have for them in the service is this :
CreateWebsiteUser()
public WebsiteUser CreateWebsiteUser(ApplicationUser appuser)
{
var user = new WebsiteUser
{
Name = appuser.UserName,
IdentityUser = appuser
};
return user;
}
RegisterWebsiteUser()
public bool RegisterWebsiteUser(WebsiteUser websiteUser)
{
try
{
this.context.WebsiteUsers.Add(new WebsiteUser {Name = websiteUser.Name, IdentityUser = websiteUser.IdentityUser});
this.context.SaveChanges();
return true;
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
And my issue is, that whenever I try to register a new user I get an exception on the this.context.SaveChanges() line, saying "A user name with the name |Name| already exists".
|Name| is basically the value of the UserName column in the ASPNetUsers Table.
I am really stuck and can't find a solution. (I can't even understand why an error like this would happen)
My DB structure seems okay to me so I guess the issue is somewhere else.
The only solution I can think of, is to completely remove my own User class and just add properties to the deafult ASP User.
Any help is greatly appreciated.
Solved it.
Leaving this here if anyone faces a similar problem.
Basically, due to some voodoo magic, that I do not understand, when you try to just add the just-created ApplicationUser to the IdenityUser's property of your custom User class, EF screws up, thinking you are using 2 data contexts.
The way to solve this is to instead use .Find(id) to find the ApplicationUser in the database, and then give that to the property.
So, instead of going
public bool RegisterWebsiteUser(ApplicationUser appUser)
{
this.context.YourUsers.Add(new YourUser {IdentityUser = appUser});
this.context.SaveChanges();
}
You do this:
public bool RegisterWebsiteUser(ApplicationUser applicationUser)
{
string id = applicationUser.Id;
var userFromDb = context.Users.Find(id);
this.context.YourUsers.Add(new YourUser {IdentityUser = userFromDB});
this.context.SaveChanges();
}

Use model data in in a service after it was saved by another service.

I have an Index controller that gets user data and saves it to a model in my application. This happens during the "CustomAuth" call below.
[CustomAuth(group = "Role-View")]
public class IndexController : Controller
{
public ActionResult Index()
{
try
{
//call to progService
return View();
}
catch (Exception e)
{
Error.Log(e, log.LogGuid, this.User.Identity.Name);
return View();
}
}
}
Here is the code I am using to assign things to my model.
public void CheckForUser(string username, string firstName, string lastName, string emailAddress, string phoneNumber)
{
var userDataModel = new UserDataModel();
userDataModel.username = username;
userDataModel.firstName = firstName;
userDataModel.lastName = lastName;
userDataModel.emailAddress = emailAddress;
userDataModel.phoneNumber = phoneNumber;
var userexists = db.PARTies.Any(x => x.ABBR_NM == username);
if (userexists)
{
var updateUser = db.PARTies.SingleOrDefault(x => x.ABBR_NM == username);
//Get and assign the partId to the model.
userDataModel.partyId = updateUser.PARTY_ID;
//Update any fields that are relevant.
updateUser.FIRST_NM = userDataModel.firstName;
updateUser.LAST_NM = userDataModel.lastName;
updateUser.ABBR_NM = userDataModel.username;
updateUser.FULL_NM = (userDataModel.firstName + " " + userDataModel.lastName);
//Save the updated Data to the database.
db.SaveChanges();
My issue is that once this is complete, I can't seem to access the user data again. I would like to call my database and use the userDataModel.partyId from the model like so. (In a service in my Business Layer.)
public List<WizardProgModel> FetchTable()
{
return db.WIZARD_PRGRSS.Where(x => x.PARTY_ID == userDataModel.partyId);
}
I am probably missing something dumb here but shouldn't I be able to reference anything I assign in my model while the application is running? Everything up to this point is server side so the View shouldn't come into play at this point.
Thank you.
You don't need to declare the model to save it as a new db entity just use the parameters from you method directly and once in your service simply go fetch the entity back from the db. and if you need it as a model in the service fetch it like so:
var userModel = db.PARTies.FirstOrDefault(x => x.ABBR_NM == username).Select(e => new = UserDataModel {
username = username,
firstName = firstName,
lastName = lastName,
emailAddress = emailAddress,
phoneNumber = phoneNumber
});
Make your read method accept the Party Id as a parameter, For how you will get it to the service I can't tell you because I simply don't have the scope of your application/solution.
public List<WizardProgModel> FetchTable(int partyId)
{
return db.WIZARD_PRGRSS.Where(x => x.PARTY_ID == partyId);
}

Why does HttpClient GetAsync() not return in Xamarin?

I'm new to Xamarin and I'm trying to create a cross-platform app where users can login using a JSON API call. A token is then returned on a successful login attempt which I can use in other API's to display user data.
It works when I use the same code in a console application, but when I run it in Xamarin the code after await client.GetAsync(url) is never reached and after a while the application breaks and I get an unknown error. Am I experiencing a deadlock?
private async void loginButton_Click(object sender, EventArgs e)
{
var login = await loginAPI(LoginPage.nameEntry.Text, LoginPage.passEntry.Text);
if (login.state == "success")
{
...
}
else
{
...
}
}
public static async Task<LoginData> loginAPI(String username, String password)
{
try
{
using (var client = new HttpClient())
{
var loginUrl = new Uri("https://my-api/login?username=" + username + "&password=" + password);
var result = await client.GetAsync(loginUrl);
return JsonConvert.DeserializeObject<LoginData>(await result.Content.ReadAsStringAsync());
}
}
catch (Exception e)
{
return null;
}
}
public class LoginData
{
[JsonProperty("state")]
public String state { get; set; }
[JsonProperty("token")]
public String token { get; set; }
}

How to connect Bot Framework dialog with api.ai client

I'm creating a bot using Bot Framework in C#
I have this piece of code :
var faq = await result;
if (faq == "Faq with menu")
{
await context.PostAsync("Under construction");
}
else if (faq == "Faq with dialog")
{
context.Call(new FaqDialog(), this.ResumeAfterOptionDialog);
}
Faq with dialog I have connected with a dialog class.
I want to connect Faq with menu with my client in Api.ai. Do you have any idea how to do it?
What I would do is to create an enum with the Faq values:
Public enum Faq{
Undefined,
Menu,
Dialog
}
Then create a method that will call Api.ai with the user message and map the intent response to the enum:
public T MatchAiIntent<T>(string message) where T : struct, IConvertible
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException("T must be an enum type!");
}
T result = default(T);
try
{
var response = apiAi.TextRequest(message);
var intentName = response?.Result?.Metadata?.IntentName;
if (intentName == null)
{
return result;
}
Enum.TryParse<T>(intentName, true, out result);
return result;
}
catch (Exception exception)
{
//logit
throw;
}
}
Then you can use it in your code:
var response = MatchAiIntent(faq);
if (response == Faq.Menu)
{
await context.PostAsync("Under construction");
}
[UPDATE]
CONNECTING TO Dialogflow (previously known as API.AI) FROM C#
Follow these steps (working example in C#)
After you create a Dialogflow agent go to the agent's settings --> General --> click on the Service Account link
You will be sent to to google cloud platform where you can create a service account
After you create a service account, there will be an option to create a KEY, create it and download the (JSON) format of it
This key will be used to connect from your C# project to the Dialogflow agent
Install Google.Cloud.Dialogflow.V2 package in your project
Create for example a Dialogflow manager class (check below for an example)
public class DialogflowManager {
private string _userID;
private string _webRootPath;
private string _contentRootPath;
private string _projectId;
private SessionsClient _sessionsClient;
private SessionName _sessionName;
public DialogflowManager(string userID, string webRootPath, string contentRootPath, string projectId) {
_userID = userID;
_webRootPath = webRootPath;
_contentRootPath = contentRootPath;
_projectId = projectId;
SetEnvironmentVariable();
}
private void SetEnvironmentVariable() {
try {
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", _contentRootPath + "\\Keys\\{THE_DOWNLOADED_JSON_FILE_HERE}.json");
} catch (ArgumentNullException) {
throw;
} catch (ArgumentException) {
throw;
} catch (SecurityException) {
throw;
}
}
private async Task CreateSession() {
// Create client
_sessionsClient = await SessionsClient.CreateAsync();
// Initialize request argument(s)
_sessionName = new SessionName(_projectId, _userID);
}
public async Task < QueryResult > CheckIntent(string userInput, string LanguageCode = "en") {
await CreateSession();
QueryInput queryInput = new QueryInput();
var queryText = new TextInput();
queryText.Text = userInput;
queryText.LanguageCode = LanguageCode;
queryInput.Text = queryText;
// Make the request
DetectIntentResponse response = await _sessionsClient.DetectIntentAsync(_sessionName, queryInput);
return response.QueryResult;
}
}
And then this can be called like this for example to get detect Intents
DialogflowManager dialogflow = new DialogflowManager("{INSERT_USER_ID}",
_hostingEnvironment.WebRootPath,
_hostingEnvironment.ContentRootPath,
"{INSERT_AGENT_ID");
var dialogflowQueryResult = await dialogflow.CheckIntent("{INSERT_USER_INPUT}");

Categories