I have a class Activity that inherit from RealmObject. I am adding it to the realm database and there's a the page that contains a weekly SfSchedule. When the user choose an appointment(all the appointment are retrieved from the database using realm) an action sheet pops up and there is an option delete.
private async void Details_CellTapped(object sender, ScheduleTappedEventArgs args) {
var action = await DisplayActionSheet("More details", "Cancel",null, "Details","Update", "Delete");
if (action == "Delete") {
realm = Realm.GetInstance();
var activityItem = (Activity)args.selectedAppointment;
realm.Write(() => realm.Remove(activityItem));
}
}
It give me an error System.InvalidCastException: Specified cast is not valid.
Please check if that InvalidCastException is occurring on the line
var activityItem = (Activity)args.selectedAppointment;
it looks like this is nothing to do with Realm.
Related
My problem is how to avoid duplication of username in xamarin using firebase.
My expected output is upon tapping the username field, if in the database, "usernametest123" is already in there and a new customer upon his/her creating account to my app, and enter a username "usernametest123", a toast will appear like "Username is already exist".
I tried this way;
my code behind.
`
async public void CreateAccount_Clicked(System.Object sender, System.EventArgs e)
{
try{
//thats how I declare some variable up to my 11 input fields
string FName = textfield_Firstname.Text;
if (string.IsNullOrEmpty(FName )){await this.DisplayToastAsync("Please Enter your first name", 1500);}
//up to 11 input fields also
CUSTOMER customer = new CUSTOMER();
customer.CustomerFName = FName;
var Savedata = await customerRepo.Save(customer);
}
catch(Exception ex){
if(ex.Message.Contains("USERNAME_EXISTS"))
{
await this.DisplayToastAsync("Username already Exist", 1500);
}
else
{
await this.DisplayToastAsync(ex.Message,1500);
}
}
}
`
any link that will posted about my concern will be appreciated thank you so much
I want to have the parameter I receive in the controller from a client be used to authorize my "POST" methods used in my projects(Users can only edit projects they are assigned to). UserIds will live on the project so I need to fetch the project and verify the current user id is in the project.
// I want to modify my policy below where I can use "projectId". ProjectId is dynamic and passed in from a ajax call
[Authorize(Policy = "CanModifyProject")]
[HttpPost]
public async Task<IActionResult> SaveWorker(var projectId, workerModel worker)
{
// Code here....
}
My policy
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CanModifyProject requirement)
{
bool isSuperAdmin = context.User.IsAdmin();
bool isAdmin = context.User.IsAdmin();
var currentUserId = context.User.GetUserId();
// I NEED TO HAVE THE DYNAMIC PROJECT ID here recieved by "POST" methods
int projectId = 0;
// Check to see if the project has the assigned User
var projectUserIsAssigned = this.projectRepository.ProjectIsAssignedToUser(projectId currentUserId);
if (isSuperAdmin || isAdmin && projectUserIsAssigned)
{
context.Succeed(requirement);
return Task.CompletedTask;
}
else
{
context.Fail();
return Task.CompletedTask;
}
}
How can I access my ProjectId in my post method ???
The authorization phase is fairly early in the request processing pipeline, before executing the action. So no view model is bound yet (by model binding). I would use an IActionFilter or IAsyncActionFilter for this purpose. There you can access the ActionExecutingContext.ActionArguments to get the bound parameter you want for your custom authorization.
Here I would like to try solving it the way you want with the code usually executed in the scope of IAuthorizationFilter or IAsyncAuthorizationFilter (there is another place in which it's executed in the AuthorizationMiddleware). With this approach, it's limited in how you get the action argument value. It should be plainly accessible via some key and the raw value we get is of course a string. As in your specific requirement, it's just a parameter of int which can be sent via form-data or query string from the client.
The point here is we can get such a raw value using a CompositeValueProvider.
The code should say it all:
//inject IOptions<MvcOptions> into your CanModifyProject requirement class
//name it as _mvcOptions
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CanModifyProject requirement) {
bool isSuperAdmin = context.User.IsAdmin();
bool isAdmin = context.User.IsAdmin();
var currentUserId = context.User.GetUserId();
var projectId = 0;
//get projectId
if(context.Resource is ActionContext ac &&
ac.ActionDescriptor is ControllerActionDescriptor ca)
{
//match only the related controller method
if(ca.ControllerTypeInfo == typeof(YourController) &&
ca.MethodInfo.Name == nameof(YourController.SaveWorker)) {
//create the composite value provider
var valueProvider = await CompositeValueProvider.CreateAsync(ac, _mvcOptions.Value.ValueProviderFactories);
//get the raw id (as string)
var id = valueProvider.GetValue("projectId").FirstValue ?? "";
//parse your projectId here
int.TryParse(id, out projectId);
}
}
//your remaining code (unchanged)
//...
}
So I use ADAL library to get id token.
I got the code sample from here
sample code
However, if I set the query string prompt to none. I would get this annoying message AADSTS50059: No tenant-identifying information found in either the request or implied by any provided credentials. If the user is not logged in when getting the code. And the screen will hang in the Microsoft login window.
I need to set it as "prompt", "consent" so even not logged in the user can still perform sign in/consent. But I wan to simply the process, not to get the user go through this sign in/consent every time.
Is there a way to do it so that for not already sign in user an call back error is returned instead of this error and hanging there forever?
According to the doc, {prompt", "none"} should be a valid configuration.
I copy the sample code here for convenient purpose:
protected void Page_Load(object sender, EventArgs e)
{
if (Request.Params["code"] != null)
{
var accesstoken = AcquireTokenWithResource(resource: "https://graph.microsoft.com/");
Response.Write(accesstoken);
}
}
protected void Button2_Click(object sender, EventArgs e)
{
GetAuthorizationCode();
}
public void GetAuthorizationCode()
{
JObject response = new JObject();
var parameters = new Dictionary<string, string>
{
{ "response_type", "code" },
{ "client_id", "clientid" },
{ "redirect_uri", "http://localhost:8099/WebForm1.aspx" },
{ "prompt", "none"},
{ "scope", "openid"}
};
var requestUrl = string.Format("{0}/authorize?{1}", EndPointUrl, BuildQueryString(parameters));
Response.Redirect(requestUrl);
}
public string AcquireTokenWithResource(string resource)
{
var code = Request.Params["code"];
AuthenticationContext ac =
new AuthenticationContext(string.Format("https://login.microsoftonline.com/{0}", "tenantID"
));
ClientCredential clcred =
new ClientCredential("clientID", "clientSecret");
var token =
ac.AcquireTokenByAuthorizationCodeAsync(code,
new Uri("http://localhost:8099/WebForm1.aspx"), clcred,resource).Result.AccessToken;
return token;
}
private string BuildQueryString(IDictionary<string, string> parameters)
{
var list = new List<string>();
foreach (var parameter in parameters)
{
list.Add(string.Format("{0}={1}", parameter.Key, HttpUtility.UrlEncode(parameter.Value)));
}
return string.Join("&", list);
}
protected string EndPointUrl
{
get
{
return string.Format("{0}/{1}/{2}", "https://login.microsoftonline.com", "tenantID", #"oauth2/");
}
}
Can you check the detailed logs of this error. If you are you using ADAL login the it could be local storage caching issue. as when ADAL login is successful it caches the login info into your browser’s local storage to eliminate the need to log in again anytime soon but in certain situations where you will be authenticating against multiple Azure AD instances it will mix-up the authentication. To fix this you will need to clear the browser's storage cache by using the developer tools(F12) then browse to “Application” tab, and then find your tenant from the “Local Storage” -section. After removing all the storage entries for ADAL refresh the page that threw the error before and you should be greeted with a fresh login screen.
Hope it helps.
I'm loading the page's data in the OnAppearing method, but this causes loading data in situations where it doesn't change, like calling PopupAsync() from another page. so I thought the messaging center would help. I made a flag field in the page, and subscribed to any message coming from outside to decide whether to update data or not,
for example this from the MenuViewModel (when the user first opens the page, so I need to load data):
var p = new FeedbackListPage();
MessagingCenter.Send(this, "loadData", "1");
await Navigation.PushAsync(p);
and in the FeedbackListPage's constructor:
InitializeComponent();
BindingContext = vm = new FeedbackViewModel(Navigation);
MessagingCenter.Subscribe<string>(this, "loadData", ( _loadData) =>
{
loadDataStr = _loadData;
});
and in the OnAppearing:
protected override void OnAppearing()
{
base.OnAppearing();
if (loadDataStr=="1")
vm.OnLoadFeedbacks();
}
the problem is that the Subscribe's action is never called!
Solution:
The API for MessagingCenter:
1.Subscribe<TSender> (object subscriber, string message, Action<TSender> callback, TSender source = null)
2.Subscribe<TSender, TArgs> (object subscriber, string message,Action<TSender, TArgs> callback, TSender source = null)
So, if you want to pass an Argument using MessageCenter, you should define both Sender and Args:
MessagingCenter.Subscribe<MainPage,string>(this, "loadData", (sender,_loadData) =>
{
loadDataStr = _loadData;
});
Refer: messaging-center
You can try the following:
use MessagingCenter.Send to send the signal when you want to update the data from any page and then in your ViewModel's constructor use MessagingCenter.Subscribe to perform the needed action
Send:
MessagingCenter.Send<namespace.App>((namespace.App)Xamarin.Forms.Application.Current, "update");
Subscribe:
MessagingCenter.Subscribe<namespace.App>((namespace.App)Application.Current, "update", (sender) => {
// update - get data
});
I need to implement chat on my web project. How to implement it on one page - there are many articles about it. But I need to have ability :
1. Notify other users, that somebody logged to site (on any page, not only on chat page)
2. Notify other users, that somebody logout
So, I have the following code of hub:
public void Connect()
{
try
{
var id = Context.ConnectionId;
string username = Context.User.Identity.Name;
var currentUser = connectedUsers.Where(p => p.Username == username).FirstOrDefault();
if (currentUser == null)
{
AddNewUserToCollection();
}
else
{
// update ConnectionId for sure (connection id is changed sometimes (probably if user is logged out and login again))
if (currentUser.ConnectionId != id)
{
var companyId = _chatRepository.GetCompanyIdOfUser(username); // throws exception if companyId is null
Groups.Remove(currentUser.ConnectionId, companyId.ToString());
Groups.Add(id, companyId.ToString());
currentUser.ConnectionId = id;
//Clients.Group(companyId.ToString()).onNewUserConnected(username);
}
}
}
catch(InvalidCompanyException c_ex)
{
Clients.Client(Context.ConnectionId).onErrorMessage($"User '{c_ex.Username}' does not exist");
}
}
public void Disconnect()
{
string username = Context.User.Identity.Name;
var item = connectedUsers.Where(p => p.Username == username).FirstOrDefault();
if (item != null)
{
connectedUsers.Remove(item);
Groups.Remove(item.ConnectionId, item.CompanyID.ToString());
Clients.Group(item.CompanyID.ToString()).onUserDisconnected(item.Username);
}
}
public override Task OnDisconnected(bool stopCalled)
{
var item = connectedUsers.Where(p => p.ConnectionId == Context.ConnectionId).FirstOrDefault();
if (item != null)
{
connectedUsers.Remove(item);
Groups.Remove(item.ConnectionId, item.CompanyID.ToString());
Clients.Group(item.CompanyID.ToString()).onUserDisconnected(item.Username);
}
return base.OnDisconnected(stopCalled);
}
and I added the following code to _layout.cshtml:
<script>
$(document).ready(function () {
var chat = $.connection.chatHub;
$.connection.hub.start().done(function () {
chat.server.connect();
});
});
</script>
to notify other users, that the current user is logged. But debugger says, that pair OnDisconnected/Connect is called every time, when user reload page (go thru pages) with different connectionId. When I remove this client code - that pair is not called. How to implement it correctly, to notify other users, that somebody is online, but without reconnect each time?
Since you have the connect() call in a razor (_layout.cshtml) page, you will effectively be disconnecting/connecting on every post back (page load).
The scenario you're trying to use is best in a SPA (or AJAX) scenario where navigation is handled asynchronously by client side JavaScript. Your current setup is refreshing the screen, reloading the JavaScript, re-running the document ready() function with each server rendered navigation.
Another alternative is to use the client's actual user Id, and pass that to the server.connect(id) method. Then use this user Id to track the user activity instead of the hub ConnectionId.