How to handle WebClient response to display error message to user? - c#

I am working on a MVC Web App which is calling a Web API. In my Create (POST) method, a user will enter email addresses of some users in the database. I have a check to enter the email only if the email does not already exist in the database or not. If it already exists, I want to be able to show an error message to the user "Email already exists".
I don't know how to handle the response to display an error message to the user when it fails to create an approveduser? I am trying with a try-catch case, but it is not working. I have ViewBag.Message = error which I am trying to display in my Index View when it fails. But nothing is displaying. When I debug, it doesn't even go to the catch when the email exists in the database, it just takes me to the Index view.
public ActionResult Create([Bind(Include = "Email,FirstName,LastName")] ApprovedUsers approvedUsers)
{
try
{
using (WebClient client = new WebClient())
{
token = Session.GetDataFromSession<string>("access_token");
client.Headers.Add("authorization", "Bearer " + token);
byte[] response = client.UploadValues(apiUrl, "POST", new NameValueCollection()
{
{ "Email", approvedUsers.Email },
{ "FirstName",approvedUsers.FirstName },
{ "LastName",approvedUsers.LastName }
});
string result = System.Text.Encoding.UTF8.GetString(response);
return RedirectToAction("Index");
}
}
catch
{
return RedirectToAction("Index", new { error = "Email exists" });
}
}
Index Action
public ViewResult Index(string sortOrder, string currentFilter, string searchString, int? page, string error)
{
ViewBag.Message = error;
This is the API method being called.
public IHttpActionResult PostApprovedUsers(ApprovedUsers approvedUsers)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (!db.ApprovedUsers.Any(u => u.Email == approvedUsers.Email))
{
db.ApprovedUsers.Add(approvedUsers);
db.SaveChanges();
}
return CreatedAtRoute("DefaultApi", new { id = approvedUsers.Email }, approvedUsers);

Try this:
public ActionResult Create([Bind(Include = "Email,FirstName,LastName")] ApprovedUsers approvedUsers)
{
try
{
using (WebClient client = new WebClient())
{
token = Session.GetDataFromSession<string>("access_token");
client.Headers.Add("authorization", "Bearer " + token);
byte[] response = client.UploadValues(apiUrl, "POST", new NameValueCollection()
{
{ "Email", approvedUsers.Email },
{ "FirstName",approvedUsers.FirstName },
{ "LastName",approvedUsers.LastName }
});
string result = System.Text.Encoding.UTF8.GetString(response);
}
}
catch
{
TempData["Error"] = "Email Exists";});
}
RedirectToAction("Index");
}
public ViewResult Index(string sortOrder, string currentFilter, string searchString, int? page, string error)
{
ViewBag.Message = TempData["Error"].ToString();
}

It was my API that was causing the issue. Even when it failed to create the duplicate email, it never went to the catch because I didn't have a bad request return if the email did exist in the database.
Changed my API to this and then it was working.
if (db.ApprovedUsers.Any(u => u.Email == approvedUsers.Email))
{
return Content(HttpStatusCode.BadRequest, "Email exists already");
}
else
{
db.ApprovedUsers.Add(approvedUsers);
}
try
{
db.SaveChanges();
}
catch (DbUpdateException e)
{
if (ApprovedUsersExists(approvedUsers.Id))
{
return Conflict();
}
throw e;

Related

Implementing PHP session in MVC C#

Currently, I am working on a web application using MVC C#. I would like to ask if there is a way to implement a PHP Session in MVC. The use of the session I am talking about is like, when you write only the link or path like this from https://localhost:44360/Login/Login to https://localhost:44360/Home/Home to go to the Home Page of the Web even if you did not sign-in using an account you will not be redirected to that page.
After I logged in to an account, I am redirected to the homepage which is correct, after that, I logged out the account and try to Type https://localhost:44360/Home/Home and unfortunately it was redirected or even clicking the back button of the browser.
I am currently working on the code below.
LoginController.cs
[HttpPost]
public ActionResult Login(LoginModel userInfo, FormCollection collection, string returnUrl)
{
ILogicInterface<LogicalUserInput, LogicalSystemResult> iLogic = new UserLoginCheck();
LogicalUserInput userInput = new LogicalUserInput();
_ = new LogicalSystemResult();
try
{
userInput[typeof(LoginModel).FullName] = userInfo;
LogicalSystemResult systemResult = iLogic.DoProcess(userInput);
bool userCheckExist = systemResult.ResultCode != LogicalSystemResult.RESULT_CODE_ERR_DATA_NOT_EXIST;
if (userCheckExist)
{
UserLoginModel loginModel = systemResult[typeof(UserLoginModel).FullName] as UserLoginModel;
Session["userInfo"] = loginModel;
FormsAuthentication.SetAuthCookie(loginModel.email, true);
if (!string.IsNullOrEmpty(returnUrl))
{
return Redirect(returnUrl);
}
else
{
if (loginModel.AccountType == 0) {
return RedirectToAction("Home", "Home");
} else {
return RedirectToAction("Error", "Error");
}
}
}
else
{
TempData.Clear();
TempData["Title"] = "Error!";
TempData["Message"] = " Invalid Username Or Password.";
return View();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return RedirectToAction("Error", "Error");
}
}
Logout Button in HOME.cshtml
<a id="cmdLogOff">
<i class="feather icon-log-out"></i>Logout
</a>
Click Event of LogoutButton
<script>
$("#cmdLogOff").on("click", function () {
$("#HomeView").submit();
});
</script>
#using (Ajax.BeginForm("LogOut",
null,
new AjaxOptions
{
},
new { id = "HomeView" }))
{
}
HOMEController.cs
[Authorize]
public ActionResult Home()
{
if (Session["userInfo"] == null) {
return RedirectToAction("Error", "Error");
} else {
UserLoginModel userLoginModel = Session["userInfo"] as UserLoginModel;
TempData["user"] = userLoginModel.lastName + ", " + userLoginModel.firstName + " " + userLoginModel.middleName;
return View();
}
}
[Authorize]
[HttpPost]
public ActionResult LogOut() {
try {
Session.Abandon();
FormsAuthentication.SignOut();
Session["userInfo"] = null;
return RedirectToAction("Login", "Login");
} catch (Exception ex) {
Console.WriteLine(ex.Message);
return View();
}
}
The main question here is that, how can I not redirect the user if he/she just only type the link he/she wants to access without an account. And after logging out of an account, the Home Page will not be shown even if the user clicked the back of the browser?

Infinite Loading on HTTPS Request with Asp.Net Razor Pages

When I try to make an HTTPS request with my Razor Page eg. a POST request then comes in the console:
info: Microsoft.AspNetCore.Hosting.Internal.WebHost [2]
Request finished in 103.9478ms 200 text / html; charset = utf-8
but the website just keeps loading and I will not be redirected to the index page
here is the code from the post method
public async Task<IActionResult> OnPost()
{
if (!ModelState.IsValid)
{
return Page();
}
if (this.RegisterViewModel.Password == this.RegisterViewModel.ConfirmPassword)
{
var profileResult = await this.dbContext.Profiles.AddAsync(new Profile
{
Id = Guid.NewGuid(),
Created = DateTime.Now,
Modified = DateTime.Now
});
var userResult = await this.userManager.CreateAsync(new ApplicationUser
{
UserName = this.RegisterViewModel.UserName,
Email = this.RegisterViewModel.Email,
ProfileId = profileResult.Entity.Id
}, this.RegisterViewModel.Password);
if (!userResult.Succeeded)
{
ModelState.AddModelError("", "Invalid credentials.");
return Page();
}
} else
{
ModelState.AddModelError("", "Passwords dosenĀ“t match.");
return Page();
}
return RedirectToPage("/Index");
}

component.ts class gives an error when the return type is iActionResult

I am a bit confuse right now. Whenever i return void from my controller class everything works fine.
my controller.cs class.
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[HttpPut("[action]")]
public void EditEmployee(Employee employee)
{
if (ModelState.IsValid)
{
_repo.edit(employee);
_repo.Save();
// return Ok($"update was successful for {employee}");
}
// return BadRequest("Something Went Wrong");
}
my service.ts class
updateEmployee(employee) {
let token = localStorage.getItem("jwt");
return this._http.put('api/Employee/EditEmployee', employee, {
headers: new HttpHeaders({
"Authorization": "Bearer " + token,
"Content-Type": "application/json"
})
})
}
and my component.ts class
onSubmit(employeeForm: NgForm) {
//console.log(employeeForm.value);
this._employeeService.updateEmployee(employeeForm.value).subscribe(
success => {
this.Message = "Record Uploaded Successfully";
},
err => this.Message = "An error Occurred"
);
the code example above works as expected and returns Record Uploaded Successfully
but whenever i change the return type in my controller.cs class to IActionResult,
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[HttpPut("[action]")]
public IActionResult EditEmployee(Employee employee)
{
if (ModelState.IsValid)
{
_repo.edit(employee);
_repo.Save();
return Ok($"update was successful for {employee}");
}
return BadRequest("Something Went Wrong");
}
it updates the record successfully in my database but returns An Error Occurred in my component.ts class
this is it on github
i want to understand what is happening and why i am experiencing this error.
Image when controller.cs file returns void
and
Image when controller.cs file returns IActionResult
Return a json object from your controller.cs class not a string literal
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[HttpPut("[action]")]
public IActionResult EditEmployee(Employee employee)
{
if (ModelState.IsValid)
{
_repo.edit(employee);
_repo.Save();
return Json(new { Message="Update was successful!"});
}
return BadRequest(new { Message="Something went wrong!"});
}

Checking the data returned for empty data while using ajax

I am using the jQuery code below to search for an employee and once the
employee exists, other fields in the table are returned.
I want to be able to send an alert to the user if the employee was not found.
How can I achieve that?
$(document).on("click", "#btnEmpNumber", function () {
var getdata = $('#EmpNumber').val();
var url = "#Url.Action("GetEmployeeInformation", "Home")";
$.post(url, { 'objdata': getdata }, function (data) {
if (data == undefined) {
alert("Invalid Employee");
}
$('#mainYourinformation').html(data);
});
});
public ActionResult GetEmployeeInformation(string objdata)
{
Customerproductdto objGetEmpData = null;
try
{
objGetEmpData = _DataService.SearchEmplByNumber(objdata);
}
catch (Exception ex)
{
logger.Error(ex);
}
return PartialView("_Empinformation", objGetEmpData);
}
public class Customerproductdto
{
public string EmployeeNumber { get; set; }
public string EmployeeName { get; set; }
public string EmployeePhone { get; set; }
public string EmployeeTitle { get; set; }
}
Assuming your SearchEmplByNumber return null when the employee was not found, you can return a different result from your action method.
public ActionResult GetEmployeeInformation(string objdata)
{
Customerproductdto objGetEmpData = null;
try
{
objGetEmpData = _DataService.SearchEmplByNumber(objdata);
}
catch (Exception ex)
{
logger.Error(ex);
}
if(objGetEmpData!=null)
return PartialView("_Empinformation", objGetEmpData);
return Content("No information found for the employee");
}
If you want fancy html markup than the simply message, create a new partial view with those fancy markup and return that.
if(objGetEmpData!=null)
return PartialView("_Empinformation", objGetEmpData);
return PartialView("NoDataFoundForEmployee");
Assuming you have a view called NoDataFoundForEmployee.cshtml in ~/Views/Shared or ~/Views/Home/
There is no need of the if condition in your $.post success callback as your action method will always return some response.
EDIT : As per the comment
I am using toastr to return messages and thats what I want to stick to
In this case, you may always return a json response from your action method with the below structure
{
status="found",
message="some Message for the user",
resultMarkup="somehtmlToDisplayToUser"
}
You can use the below helper method(took from this answer) to convert your view result to a string
public string RenderRazorViewToString(string viewName, object model)
{
ViewData.Model = model;
using (var sw = new StringWriter())
{
var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext,
viewName);
var viewContext = new ViewContext(ControllerContext, viewResult.View,
ViewData, TempData, sw);
viewResult.View.Render(viewContext, sw);
viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
return sw.GetStringBuilder().ToString();
}
}
Now in your action method,
public ActionResult GetEmployeeInformation(string objdata)
{
Customerproductdto objGetEmpData = null;
try
{
objGetEmpData = _DataService.SearchEmplByNumber(objdata);
}
catch (Exception ex)
{
logger.Error(ex);
return Json(new { status="error", message="System Error!" });
}
if(objGetEmpData!=null)
{
var h= RenderRazorViewToString("_Empinformation", objGetEmpData);
return Json(new { status="found", resultMarkup = h });
}
return Json(new { status="notfound", message="Employee not found" });
}
Now in your $.post method's callback, check the json response's status property value and show the markup or messsage.
$.post(url, { 'objdata': getdata }, function (data) {
if (data.status==="found") {
$('#mainYourinformation').html(data.resultMarkup);
}
else
{
alert(data.message);
// or call the toastr method here
// toastr.error(data.message, 'Not found')
}
});
Return the exception from controller and catch that exception in catch block of $.post method and show alert to the user.
$.post(url, { 'objdata.....).catch (function (ex){
alert (ex);
});

Using register/login actions in asp.net mvc

I have a problem starting a new asp.net application. I choose asp.net mvc template with Individual User Accounts authentication and project generates and starts normally. My question is: what do i have to do to use register/login options? From what I understood methods responsible for these actions are generated automatically, but should I do something about database schema for information about users (shoudn't it be created also automatically?).
Anyway, after filling fields in register form i get error that a file couldn't be found and the error is found on line 155: var result = await UserManager.CreateAsync(user, model.Password);
I'm using Visual Studio Community 2015 on windows 8. Thank you in advance
public async Task<IActionResult> Register(RegisterVM registerVM)
{
if (!ModelState.IsValid)
{
return View();
}
AppUser appUser = new AppUser()
{
Fullname = registerVM.Fullname,
UserName = registerVM.Username,
Email = registerVM.Email
};
IdentityResult result = await _userManager.CreateAsync(appUser, registerVM.Password);
if (!result.Succeeded)
{
foreach (var error in result.Errors)
{
ModelState.AddModelError("", error.Description);
}
return View(registerVM);
}
await _userManager.AddToRoleAsync(appUser, Roless.Admin.ToString());
await _signInManager.SignInAsync(appUser, true);
return RedirectToAction("index", "home");
}
public IActionResult Login()
{
return View();
}
[HttpPost]
[AutoValidateAntiforgeryToken]
public async Task<IActionResult> Login(LoginVM loginVM, string returnurl)
{
if (!ModelState.IsValid)
{
return View();
}
AppUser dbUser = await _userManager.FindByEmailAsync(loginVM.Email);
if (dbUser == null)
{
ModelState.AddModelError("", "Ya email ya da Password sehvdir");
return View(loginVM);
}
SignInResult result = await _signInManager.PasswordSignInAsync(dbUser, loginVM.Password, loginVM.RememerMe, true);
if (result.IsLockedOut)
{
ModelState.AddModelError("", "Your Account Is Lock Out");
return View(loginVM);
}
if (!result.Succeeded)
{
ModelState.AddModelError("", "Ya Email ya da Password sehvdir");
return View(loginVM);
}
if (returnurl == null)
{
return RedirectToAction("index", "home");
}
foreach (var item in await _userManager.GetRolesAsync(dbUser))
{
if (item.Contains(Roless.Admin.ToString()))
{
return RedirectToAction("index", "Dashboard", new { area = "AdminF" });
}
}
return Redirect(returnurl);
}

Categories