I have a controller method from which I would like to return to my angular client some error condition when account object is null. I used exception below and it works, but is there a better way of reporting error string to the angular client then the below one.
[Authorize]
[HttpPost("get-schedule-from-pool/{id}")]
public ActionResult<AccountResponse> GetScheduleFromPool(int id, UpdateScheduleRequest scheduleReq)
{
// users can update their own account and admins can update any account
if (id != Account.Id && Account.Role != Role.Admin)
return Unauthorized(new { message = "Unauthorized" });
var account = _accountService.GetScheduleFromPool(id, scheduleReq);
if(account == null)
{
// Request.Body.
// return HttpError("Function :" + scheduleReq.UserFunction + " for date: " + scheduleReq.Date + " already taken");
throw new Exception("Sample exception.");
}
return Ok(account);
}
If you want to return a error message or error code to the client there's a few ways to do it.
Using StatusCode:
return StatusCode(StatusCodes.Status500InternalServerError,"Details");
or
return StatusCode(500,"Details")
Or using the default wrappers:
return Problem("Details");
Here a list of all error codes and what they mean.
Related
I am creating a small demo for reset password in web API and identity using in .net MVC c#.and I am clicking on forgot password send one code in the mail using a query string. In the mail code is correct getting. now I am going for the change password and getting the code from the URL not getting propare in the token '==' last end not getting and get error invalid token how can do fix it this error anyone knows?
this my ForgotPassword method in Account Controller :
public async Task<IHttpActionResult> ForgotPassword(ForgotPasswordViewModel model)
{
try
{
var user = await UserManager.FindByNameAsync(model.Email);
if (user == null)
{
return Ok();
}
// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=320771
// Send an email with this link
string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
await UserManager.SendEmailAsync(user.Id, "Reset Password",Request.RequestUri.GetLeftPart(UriPartial.Authority) + "/home/ChangePassword?Code=" + code);
return Ok("Ok");
}
catch (Exception ex)
{
ExceptionsLogging.SendExcepToDB(ex);
throw new HttpException(500, ex.Message);
}
}
this is my ResetPasswordMethod :
public async Task<IHttpActionResult> ResetPassword(ChangePasswordBindingModel model)
{
try
{
var user = await UserManager.FindByNameAsync(model.Email);
if (user == null)
{
// Don't reveal that the user does not exist
return Ok();
}
var result = await UserManager.ResetPasswordAsync(user.Id, model.Code, model.NewPassword); // here not getting code propare
if (result.Succeeded)
{
return Ok("Done");
}
return Ok();
}
catch (Exception ex)
{
ExceptionsLogging.SendExcepToDB(ex);
throw new HttpException(500, ex.Message);
}
}
any one know how can fix it i am try encode/decode but now getting propare
You must encode the generated token before sending the email
string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
var encodedCode = HttpUtility.UrlEncode(code);
await UserManager.SendEmailAsync(user.Id, "Reset Password",Request.RequestUri.GetLeftPart(UriPartial.Authority) + "/home/ChangePassword?Code=" + encodedCode);
return Ok("Ok");
If I'm trying to send an email immediately a new email has been confirmed, how to I go about it ?
The piece of code below is what I have in ConfirmEmail method. When I run the code, I get Exception Details: System.NullReferenceException: Object reference not set to an instance of an object. on await UserManager.SendEmailAsync(userId, "API", "API Code is: " + user.ApiCode);
I think UserManager.FindById is not returning anything, but not sure how to go about it.
Any pointers/ideas will help.
public async Task<ActionResult> ConfirmEmail(string userId, string code)
{
if (userId == null || code == null)
{
return View("Error");
}
var result = await UserManager.ConfirmEmailAsync(userId, code);
var user = UserManager.FindById(User.Identity.GetUserId());
await UserManager.SendEmailAsync(userId, "API", "API Code is: " + user.ApiCode);
return View(result.Succeeded ? "ConfirmEmail" : "Error");
}
With the info you provided I guess maybe the problem is that the user is not authenticated and therefore User.Identity will return null, hence the NullReferenceException.
You could try to fetch the user information with the id you're receiving in the action parameter userId instead.
public async Task<ActionResult> ConfirmEmail(string userId, string code)
{
if (userId == null || code == null)
{
return View("Error");
}
var result = await UserManager.ConfirmEmailAsync(userId, code);
//var user = UserManager.FindById(User.Identity.GetUserId());
var user = UserManager.FindById(userId); //use the received parameter to get the user
await UserManager.SendEmailAsync(userId, "API", "API Code is: " + user.ApiCode);
return View(result.Succeeded ? "ConfirmEmail" : "Error");
}
Hope this helps!
I have method where it takes some parameter and the response is in json format.
On success it will return int type value.
But if error occurs then rest service will throw exception where as the method which is implements the REST service must return int value.
internal static int AddCatalog(string name, Guid key, string userName)
{
using (var client = new HttpClient())
{
HttpResponseMessage response = client.PutAsync(AdminRestServiceUrl + "xml/updatecatalog?cid=" + null + "&name=" + name + "&key=" + key + "&uby=" + userName, null).Result;
response.EnsureSuccessStatusCode();
var cid= response.Content.ReadAsStringAsync().Result;
return Convert.ToInt32(cid);
}
}
How can I handle it effieciently, if service throws error?
if i do like this
if(response.IsSuccessStatusCode == HttpStatusCode.OK)
{
return convert.ToInt32(cid);
}
else
{
return ?? //how to handle error here as method must retun int type
}
Please suggest how should I pass the detailed error message to the clients in order to notify them the exact error occurred in the service.
Any kind of help/suggestion is greatly appreciated.
you can do possibly Make an "ErrorLogs" Class ,Keep "Status" Field in it , and the Error Exception in "Message" Field , if there occurs any error send status to failed
In both Cases return a Class Which has both Error Logs and and Integer Value, if there is error Return Integer as -1 and handle it on Client
I am getting a lot of these in my event viewer:
Event code: 4006
Event message: Membership credential verification failed.
Event time: 1/18/2014 11:33:27 AM
Event time (UTC): 1/18/2014 5:33:27 PM
Event ID: dd4b04a795db4e5ab5fafd8243280047
Event sequence: 1224
Event occurrence: 28
Event detail code: 0
Application information:
Application domain: /LM/W3SVC/3/ROOT/SuburbanCustPortal-1-130345141090318852
Trust level: Full
Application Virtual Path: /SuburbanCustPortal
Application Path: C:\inetpub\secure.ssswebportal.com\SuburbanCustPortal\
Machine name: WIN-OB929P97YAR
Process information:
Process ID: 4384
Process name: w3wp.exe
Account name: NT AUTHORITY\NETWORK SERVICE
Request information:
Request URL: http://myurl.com:443/SuburbanCustPortal/Account/Logon2
Request path: /SuburbanCustPortal/Account/Logon2
User host address: xxx.xxx.xxx.xxx
User:
Is authenticated: False
Authentication Type:
Thread account name: NT AUTHORITY\NETWORK SERVICE
Name to authenticate: nancyduve
Custom event details:
It seems to be always happening on the Logon2 url.
Here is my Logon2:
public ActionResult Logon2(LogOnModel model, string returnUrl, string corpid)
{
var control = Logging.StartLog();
control.Source = SourceEnum.WebPortal;
control.SessionId = Session.SessionID;
try
{
Logging.WriteLog("Starting Logon2");
Logging.WriteLog("returnUrl: " + returnUrl);
Logging.WriteLog("corpid: " + corpid);
Logging.WriteLog("model.UserName: " + model.UserName);
Logging.WriteLog("model.Password: " + model.Password);
Logging.WriteLog(string.Format("ModelState.IsValid: {0}", ModelState.IsValid));
if (ModelState.IsValid)
{
if (Membership.ValidateUser(model.UserName, model.Password))
{
Logging.WriteLog("Validated User");
Logging.WriteLog(string.Format("model.UserName: {0}", model.UserName));
FormsAuthentication.SetAuthCookie(model.UserName, true);
if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1
&& returnUrl.StartsWith("/")
&& !returnUrl.StartsWith("//")
&& !returnUrl.StartsWith("/\\"))
{
Logging.WriteLog("Redirect(returnUrl)");
return Redirect(returnUrl);
}
Logging.WriteLog("Start _client.RequestCustomersForAccount(model.UserName)");
var customer = _client.RequestCustomerForAccount(model.UserName);
// ********** NO ACCOUNTS FOUND ************
// No customers assigned to this login
// take them to the add account screen
if (customer == null)
{
// no accounts tied to this logon
Logging.WriteLog("No accounts found for this login.");
Logging.WriteLog("RedirectToAction(AddCustomer, Customer)");
// we need to make sure the branch account number is blank from any prior visits
Session[SessionEnums.CurrentAccountGuid.ToString()] = string.Empty;
Session[SessionEnums.CurrentBranchNumber.ToString()] = string.Empty;
Session[SessionEnums.CurrentAccountNumber.ToString()] = string.Empty;
return RedirectToAction("AddCustomer", "Customer");
}
// the account's tokenid that was used when the account was created
// takes presidence over the one being passed in since the account
// login is specific to the original company that they signed up with
Guid acctguid;
if (Guid.TryParse(customer.AccountId, out acctguid))
{
var tokenid = _client.GetAccountTokenId(acctguid);
if (tokenid != Guid.Empty)
{
GetCookieInfo.TokenId = tokenid.ToString();
Session[SessionEnums.TokenId.ToString()] = tokenid.ToString();
}
}
Logging.WriteLog("RedirectToAction(AccountScreen, Customer)");
model.AccountId = customer.AccountId;
// save this account info in the cookie and session
Session[SessionEnums.CurrentAccountGuid.ToString()] = customer.AccountId;
Session[SessionEnums.CurrentBranchNumber.ToString()] = customer.Branch;
Session[SessionEnums.CurrentAccountNumber.ToString()] = customer.AccountNumber;
Logging.WriteLog(string.Format("customer.AccountId: {0}", customer.AccountId));
Logging.WriteLog(string.Format("customer.Branch: {0}", customer.Branch));
Logging.WriteLog(string.Format("customer.AccountNumber: {0}", customer.AccountNumber));
// only 1 account tied to this logon
return RedirectToAction("AccountScreen", "Customer");
}
else
{
var user = Membership.GetUser(model.UserName);
if (user != null && user.IsLockedOut)
{
const string lockedmsg =
"This account has been locked due to too many login attempts. Please reset your password to unlock this account.";
Logging.WriteLog(lockedmsg);
ModelState.AddModelError(string.Empty, lockedmsg);
}
if (user != null && !user.IsApproved)
{
const string lockedmsg =
"This account has been registered but the email that was sent was never authenticated. Please check your email account for this email.";
Logging.WriteLog(lockedmsg);
ModelState.AddModelError(string.Empty, lockedmsg);
}
else
{
const string msg = "Invalid username or password.";
Logging.WriteLog(msg);
ModelState.AddModelError(string.Empty, msg);
}
}
}
// If we got this far, something failed, redisplay form
return View("Logon");
}
catch (Exception ex)
{
Logging.WriteLog(string.Format("exception: {0}", ex.Message));
Logging.WriteException(ex);
return View("Logon");
}
finally
{
Logging.WriteLog(control, "End Logon2");
}
}
Am I missing something in my code or is this a normal log?
Have you checked that your ApplicationName in your Web.Config has been set up correctly? That's when I've seen this error the most.
Alternatively it's possible you have a user (nancy) who is locked out and she keeps trying to log in, have you enabled locking users out and could you check to see if she meets this criteria?
I am using Azure Mobile Services (following the standard Azure TodoItems tutorial), and the most basic GET method that they provide is:
public IQueryable<MyModel> GetAllMyInfo()
{
return Query();
}
This works, but I am trying to extend it so that the method will only return MyModel data for an authenticated user (identified by the X-ZUMO-AUTH authentication header standard for Mobile Service API calls). So I modified the code for:
public IQueryable<MyModel> GetAllMyInfo()
{
// Get the current user
var currentUser = User as ServiceUser;
var ownerId = currentUser.Id;
return Query().Where(s => s.OwnerId == ownerId);
}
This also works when a valid auth token is passed. However, if an invalid auth header is passed, then the currentUser is null, and the query fails (obviously). So I am trying to check for null and return a BadRequest or a 403 HTTP code. Yet a simple `return BadRequest("Invalid authentication") gives a compilation error:
public IQueryable<MyModel> GetAllMyInfo()
{
// Get the current user
var currentUser = User as ServiceUser;
if(currentUser == null) {
return BadRequest("Database has already been created."); // This line gives a compilation error saying I need a cast.
}
var ownerId = currentUser.Id;
return Query().Where(s => s.OwnerId == ownerId);
}
Does anyone know how to check for a valid authentication token and return a 403 on this method (which wants an IQueryable return type?
You can use the [AuthorizeLevel] attribute on this method to indicate that a valid token must be present in order for the method to be invoked. It will return a 401 if not.
So your full method would be:
[AuthorizeLevel(AuthorizationLevel.User)]
public IQueryable<MyModel> GetAllMyInfo()
{
// Get the current user
var currentUser = User as ServiceUser;
var ownerId = currentUser.Id;
return Query().Where(s => s.OwnerId == ownerId);
}
Please note that for the Azure Mobile Apps SDK (not Mobile Services), the above attribute is simply replaced with [Authorize].
I know this is a bit late, but will document here for you and others that may come looking for a similar problem.
(While agreeing with Matt that a 403 could/should be achieved with a [Authorize] attribute, the question is regarding returning a different HttpStatusCode OR IQueryable)
I had a similar scenario where I needed to validate some query parameters and either return my results or a HttpError (in my case I wanted a 404 with content).
I found 2 ways, either keeping the return as IQueryable<T> and throwing a HttpResponseException or changing the return to IHttpActionResult and returning normal with HttpStatusCode or Ok(Data).
I found to prefer the later as throwing an Exception would be breaking the execution while in debug and not a very pleasant development experience.
Option 1 (Preferred)
//Adding Return annotation for API Documentation generation
[ResponseType(typeof(IQueryable<MyModel>))]
public IHttpActionResult GetAllMyInfo()
{
// Get the current user
var currentUser = User as ServiceUser;
if(currentUser == null) {
return BadRequest("Database has already been created.");
}
var ownerId = currentUser.Id;
return Ok(Query().Where(s => s.OwnerId == ownerId));
}
Option 2 (Throwing Exception)
public IQueryable<MyModel> GetAllMyInfo()
{
// Get the current user
var currentUser = User as ServiceUser;
if(currentUser == null) {
throw new HttpResponseException(System.Net.HttpStatusCode.BadRequest)
// Or to add a content message:
throw new HttpResponseException(new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.BadRequest) {
Content = new System.Net.Http.StringContent("Database has already been created.")
});
}
var ownerId = currentUser.Id;
return Query().Where(s => s.OwnerId == ownerId);
}