Blazor navigate to navigating to correct page and immediately back to current page - button

I have a button on an edit page that I want to execute an entity query and then navigate back to the main page.
<button class="btn" #onclick="(() => UpdateEmpById(Emp))">Save Emp</button>
The method this button is calling can be seen below...
`private async Task UpdateEmpById(Emp emp)
{
if (emp is null || IsBusy)
{
return;
}
IsBusy = true;
try
{
using var context = ContextFactory.CreateDbContext();
List<Emp > Temp = await context.Emps
.Where(x => x.Id == emp.id)
.ToListAsync();
}
catch (DbUpdateConcurrencyException)
{
ErrorMessage = "The employee was modified. Please reload the page";
}
catch (Exception ex)
{
ErrorMessage = $"Error while saving employee: {ex.Message}";
}
finally
{
IsBusy = false;
}
NavigationManager.NavigateTo($"/");
}`
The page navigates back to "/" and immediately back to the current page and I am unsure why.
I am somewhat new to Blazor and do not know what to try currently.

Related

ASP.NET Core 5.0 MVC - generate pop up message in controller

I don't really have an idea how to handle it.
Idea is simple: user presses next page button, but returned data is empty, which means previous page was the last one. User is redirected to current page (last one with data) so they won't go too far, but I want to inform them why they can't go further.
[HttpGet]
public IActionResult Index(int page = 1)
{
var data = new List<DataModel>();
page = page < 1 ? 1 : page;
ViewBag.CurrentPage = page;
try
{
var data = ...get data...
if (data.Count == 0 && page > 1)
{
//declare pop up message
return RedirectToAction("Index", new { page = page - 1 });
}
}
catch (TimeoutException)
{
return RedirectToAction("Index", "Error");
}
return View(data);
}
I tried some googling but it looks like troublesome task, and even if it works in one browser, it won't work in the other. I don't expect that you will do this for me, but I would like some guidance which solution is optimal.
One approach would be to define a custom parameter in your Index method:
[HttpGet]
public IActionResult Index(int page = 1, bool isLastPage = false) {
/* ... */
}
Now by default this is false. Now you can check, whether it is true and set your ViewModel or ViewBag/Data flag accordingly:
[HttpGet]
public IActionResult Index(int page = 1)
{
var data = new List<DataModel>();
page = page < 1 ? 1 : page;
ViewBag.CurrentPage = page;
//pass flag to view here
ViewBag.IsLastPage = isLastPage;
try
{
var data = ...get data...
if (data.Count == 0 && page > 1)
{
//declare pop up message
return RedirectToAction("Index", new { page = page - 1, isLastPage = true });
}
}
catch (TimeoutException)
{
return RedirectToAction("Index", "Error");
}
return View(data);
}
In your RedirectToAction call you set your flag to true, so in the redirect it will be triggered.

Hot to Add Include DropDown List in ASP.net in my code below. I want to Include foreign table Item Location to my Item table

Below is my HTTP GET and HTTP POST Codes. I want to add .Include Item Location for my drop down list. Please help identity where I can add the Include for my Item Location on below code. Thank you!
Below Is my HTTPGET Method...
[HttpGet]
public ActionResult AddOrEditItem(int id = 0)
{
Item item = new Item();
if (id != 0)
{
using (erpdb db = new erpdb ())
{
item = db.Items.Where(x => x.ItemId == id).FirstOrDefault<Item>();
}
}
return View(item);
}
Below Is my HTTPPOST Method
[HttpPost]
public ActionResult AddOrEditItem(Item item)
{
try
{
using (erpdb = new erpdb())
{
if (item.ItemId == 0)
{
db.Items.Add(item);
db.SaveChanges();
}
else
{
db.Entry(item).State = EntityState.Modified;
db.SaveChanges();
}
}
return Json(new { success = true, html = GlobalClass.RenderRazorViewToString(this, "ViewAllItems", GetAllItems()), message = "Submitted Successfully" }, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
return Json(new { success = false, message = ex.Message }, JsonRequestBehavior.AllowGet);
}
}
Please help how can I add my Item Location so that it can be selected on my dropdownlist view and as well as saved
I was able to solve my own issue myself by doing the following:
Step 1: Creating a viewmodel for items so that I can include item location on my form
Step 2: added .Include when calling the database so that I can include it to my indes view of items

Error with EF when trying to save changes

I have an angular 8 app with .net core web api 2.1 and MS SQL SERVER.
I have login and logout implementation for users.
After the user logins, he can add or delete programming langugages.
When I perform a delete operation, I get the error
database operation expected to affect 1 row(s) but actually effected
5 rows
But the code works properly for finding that particular user and the ID of the programming language that he wants to delete.
Here is the image from the table: https://imgur.com/a/taZtJ7d
As you can see there are no duplicates.
I think it is something about Concurrency Conflicts. That's why I added a try-catch block with DbUpdateConcurrencyException.
It works sometimes and sometimes not.
Here, you can find the definiton for the table https://imgur.com/a/YMCYkNy
When I try the following method to delete Users from MS SQL, it works as it should:
public async Task<IActionResult> DeleteProgrammingLanguage(string userId, int plId)
{
UserPL ps = new UserPL();
try
{
ps = await _context.PlUsers.Where(x => x.UserId == userId && x.ProgrammingLanguageId == plId).SingleAsync();
_context.PlUsers.Remove(ps);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException ex)
{
throw ex;
}
return Ok(ps);
}
I solved my problem with this solution.
public IActionResult DeleteProgrammingLanguage(string userId, int plId)
{
using (_context)
{
// Fetch a person from database and change phone number
var ps = _context.PlUsers.FirstOrDefault(x => x.UserId == userId && x.ProgrammingLanguageId == plId);
// Change the person's name in the database to simulate a concurrency conflict
_context.PlUsers.Remove(ps);
var saved = false;
while (!saved)
{
try
{
// Attempt to save changes to the database
_context.SaveChanges();
saved = true;
}
catch (DbUpdateConcurrencyException ex)
{
foreach (var entry in ex.Entries)
{
if (entry.Entity is UserPL)
{
var proposedValues = entry.CurrentValues;
var databaseValues = entry.GetDatabaseValues();
foreach (var property in proposedValues.Properties)
{
var proposedValue = proposedValues[property];
var databaseValue = databaseValues[property];
// TODO: decide which value should be written to database
// proposedValues[property] = <value to be saved>;
}
// Refresh original values to bypass next concurrency check
entry.OriginalValues.SetValues(databaseValues);
}
else
{
throw new NotSupportedException(
"Don't know how to handle concurrency conflicts for "
+ entry.Metadata.Name);
}
}
}
}
}
return NoContent();
}

can not show alertcontroller when page is displayed using PushModalAsync

I am trying to show toast message in android and iOS from xamarin.forms project using Dependency Service. In iOS project message is shown on MainPage or NavigationPage. but when I navigate a second page on button click using PushModalAsync, message is not displayed.
How I navigate the page
public LoginPage()
{
Device.BeginInvokeOnMainThread(() =>
{
CustomToast.LongMessage("Hiiiiii"); // Message shown
});
Navigation.PushModalAsync(new RegisterPage()); //Doesn't show
//var reg = new RegisterPage();
//Application.Current.MainPage = reg; // toast shown here
}
Code for alertController in iOS :
const double SHORT_DELAY = 2.0;
NSTimer alertDelay;
UIAlertController alert;
public void LongAlert(string message)
{
ShowAlert(message, LONG_DELAY);
}
public void ShortAlert(string message)
{
ShowAlert(message, SHORT_DELAY);
}
void ShowAlert(string message, double seconds)
{
try
{
if (alert == null && alertDelay == null)
{
alertDelay = NSTimer.CreateScheduledTimer(seconds, (obj) =>
{
Device.BeginInvokeOnMainThread(() =>
{
DismissMessage();
});
});
Device.BeginInvokeOnMainThread(() =>
{
try
{
alert = UIAlertController.Create("", message, UIAlertControllerStyle.ActionSheet);
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(alert, true, null);
}
catch (Exception ex)
{
var Error = ex.Message;
}
});
}
}
catch (Exception ex)
{
TraceLog("Message iOS ShowAlert : " + ex.Message);
}
}
void DismissMessage()
{
if (alert != null)
{
alert.DismissViewController(true, null);
alert = null;
}
if (alertDelay != null)
{
alertDelay.Dispose();
alertDelay = null;
}
}
And I call this from my register page constructor
Device.BeginInvokeOnMainThread(() =>
{
CustomToast.LongMessage("Hiiiiii");
});
It doesn't go in catch anywhere but its not displayed also. can anyone please suggest some advice ?
This is because RegisterPage is a presented page on your LoginPage, UIApplication.SharedApplication.KeyWindow.RootViewController this code can't retrieve a correct view controller for RegisterPage. It just presented an action sheet on the previous page, but your app has reached a new page then this Toast can be shown on the screen.
Firstly, you have to find out the top page on the window:
UIViewController topViewControllerWithRootViewController(UIViewController rootViewController)
{
if (rootViewController is UITabBarController)
{
UITabBarController tabBarController = (UITabBarController)rootViewController;
return topViewControllerWithRootViewController(tabBarController.SelectedViewController);
}
else if (rootViewController is UINavigationController)
{
UINavigationController navigationController = (UINavigationController)rootViewController;
return topViewControllerWithRootViewController(navigationController.VisibleViewController);
}
else if (rootViewController.PresentedViewController != null)
{
UIViewController presentedViewController = rootViewController.PresentedViewController;
return topViewControllerWithRootViewController(presentedViewController);
}
return rootViewController;
}
Secondly, adjust your presenting code like:
Device.BeginInvokeOnMainThread(() =>
{
try
{
alert = UIAlertController.Create("", messages, UIAlertControllerStyle.ActionSheet);
topViewControllerWithRootViewController(UIApplication.SharedApplication.KeyWindow.RootViewController).PresentViewController(alert, true, null);
}
catch (Exception ex)
{
var Error = ex.Message;
}
});
At last, you could show your toast using Navigation.PushModalAsync(new RegisterPage());

Xamarin forms: Selected picture is not showing in UI from gallery and camera for IOS

Complete Scenario
I have an add icon on one page, it will show camera and gallery options when tap. If choose the camera, I will open another content page and open camera there. But the captured picture is not showing in the UI. Same for the gallery, selected image from the gallery is not showing in UI. This feature is working fine in android and not working in IOS.
Codes
When click add icon
string action = await DisplayActionSheet(null, "Cancel", null, "Camera", "Gallery");
if (action == "Camera")
{
await Navigation.PushModalAsync(new NewTweetPage("Camera"));
}
else if (action == "Gallery")
{
await Navigation.PushModalAsync(new NewTweetPage("Gallery"));
}
When entering next page
public NewTweetPage(String medium)
{
InitializeComponent();
if (medium == "Camera" )
{
OpenMyCamera();
}
else if(medium == "Gallery")
{
OpenMygallery();
}
}
public async void OpenMyCamera()
{
try
{
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
{
await DisplayAlert("Camera", "No camera available.", "OK");
return;
}
_mediaFile = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
{
Directory = "Sample",
Name = "test.jpg",
AllowCropping = true
});
if (_mediaFile == null)
return;
tweetPicture.Source = ImageSource.FromStream(() =>
{
isPicture = true;
return _mediaFile.GetStream();
});
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("Exception:>" + ex);
}
}
public async void OpenMygallery()
{
try
{
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsPickPhotoSupported)
{
await DisplayAlert("Gallery", ":( No photos available.", "OK");
return;
}
_mediaFile = await CrossMedia.Current.PickPhotoAsync();
if (_mediaFile == null)
return;
tweetPicture.Source = ImageSource.FromStream(() =>
{
isPicture = true;
return _mediaFile.GetStream();
});
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("Exception:>" + ex);
}
}
The same code is working fine in profile page part, but in that case, there is no page navigation, everything is happening on the same page.
Don't know what is the problem with the current code, please help me to solve this issue.
Putting navigation commands in the constructor can cause issues. I would recommend putting them in the OnAppearing override. Also, instead of having a try...catch around a large section of code, you should handle null-checks or similar in code.

Resources