Read API Response Messages - asp.net-mvc

I have Developed ASP.net Core Web API & Web APP Which are in the same solution but different projects.
in the API I have some validations/checking as you may call.
e.g: if user email already exists, the API returns 'Email alreday in use' like this
bool EmailExists = dbContext.Users.Any(u => u.Email == user.Email);
if (EmailExists)
{
return new JsonResult("Email Address already taken!, Try a differen Email");
}
and so on. in some cases I may need to check multiple columns one a time, (eg: UserName, Email, TellNum)
This is an example of calling the API in the MVC
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(_baseAPIUrl);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage Res = await client.PostAsJsonAsync("Users", user);
if (Res.IsSuccessStatusCode)
{
//in here I want check the `Res` and if it contains the returned messages, I want to display them by assigning it to `TempData[infoMsg]`
// else some something(register user)
}
// Check the returned JsonResult messages here if statusCode is ultered eg: BadRequest
}
My Question is how can I display these types of response messages in razor view in the MVC(Web App). in PostMan its workin, returning the response messages in body.
I did a lot of research about this but couldn't come to conclusion. I also cantacted some Devs I know(not .NET) and they said use JavaScript to call your API, which means I have to change almost everything I have done so far.
I aslo tried ultereing the statuCode to something like BadRequest in the API(if Email exists) in which case it will be checked outside the if (Res.IsSuccessStatusCode) of the Httpclient.
any help or direction is highly appreciated.

You should return a http error and a body containing some data about it eg field and message to your mvc controller. That could be a 422 error or whatever you like really since it's effectively internal and just coming back to the mvc controller.
The controller can then add any such error to modelstate and you can use the razor model "client" validation mechanism to show the error associated with a field.
This is therefore using the same mechanism used for attribute validation in the controller where you'd do
if (!ModelState.IsValid)
This is air code but will hopefully give you the idea.
[HttpPost]
public ActionResult PostUpdate(User u)
{
// call service and await response
var response = await httpClient.PostAsJsonAsync(posturi, u);
var returnContent = await response.Content.ReadAsAsync<ReturnContent>();
if (response.Result != HttpStatusCode.OK)
{
ModelState.AddModelError(returnContent.FieldName,returnContent.Error);
return Page();
}
// etc
You will want a more sophisticated checking on errors of course and check you get the body you're expecting.
Maybe you just hard code the field and error message if there's only one possibility. Maybe work with an array of fields and errors if there could be numerous validation fails.

Related

Spring OAuth2.0: How can I add a custom query parameter to the Authorization code (/oauth/authorize) response?

I see that the authorization code is inserted into the redirectUri here inside AuthorizationEndpoint.java
private String getSuccessfulRedirect(AuthorizationRequest authorizationRequest, String authorizationCode) {
if (authorizationCode == null) {
throw new IllegalStateException("No authorization code found in the current request scope.");
}
Map<String, String> query = new LinkedHashMap<String, String>();
query.put("code", authorizationCode);
String state = authorizationRequest.getState();
if (state != null) {
query.put("state", state);
}
return append(authorizationRequest.getRedirectUri(), query, false);
}
I would love to be able to just add a snippet of code just where that query.put() is but i was unable to extend the class successfully. I couldn't figure out where/how to configure this as the auth endpoint I wanted to hit first. I also found it a bit extreme that I would need to extend the entire class just so i can add a few lines of code in order to append another query parameter to the authorization code response uri.
Thanks
I am not sure why my question received a downvote, but anyways...
Since #dur's comment basically said I could not do that. Thanks btw (I don see any way to upvote your comment, I am new to SO).
Solution: I decided to create a custom authentication filter that filtered before the login page appeared. I did some validation and passed it along for authentication. From there, I added a custom success handler for my filter and redirected to /oauth/authorize in order to jump into my intended authorization code flow.

Returning result for .net Web Api from db call

I'm new to the .net Web API and am trying to figure out how I return a Get result from a call to my database. I know everything works in my regular MVC page. But Not sure how to return the result from the Web API controller. I thought it was as simple as returning Json with the result. Here is my code:
// GET api/<controller>
public IEnumerable<string> Get()
{
using (var _db = new JobsDatabaseEntities())
{
var user = Env.CurrentUser;
var posts =
_db.JobPostings.Where(
j =>
j.City.Equals(user.City, StringComparison.OrdinalIgnoreCase) &&
j.Industry.ID == user.Industry.ID);
var result = new List<BusJobPost>();
foreach (var post in posts)
{
var p = new BusJobPost(post);
result.Add(p);
}
return Json(result);
}
}
Please visit this resource: Action Results in Web API 2. Your case is described in fourth section Some other type (which is applicable to first version of Web API as well).
In Web API you don't return JSON result explicitly. It is actually done by process called Content Negotiation. You can read about it here [Content Negotiation in ASP.NET Web API] in detail.
Highlighting briefly just some of this:
You can set Accept header for you request as: Accept: application/json (for example, if you use jquery ajax function: dataType: 'json')
Or even if you don't use Accept header at all, if you send request with JSON data, you should also get response back in JSON format
So you should just return result variable from your controller action and satisfy some of conditions to get response serialized into JSON.

ValidateInputAttribute not working in Post Request of ASP.NET MVC controller

My understanding was OOTB, MVC will validate input to prevent XSS Attack and SQL Injection.
For example, In one of my app, the "a dangerous input has been detected" error will be received when I put in HTTP Get request. However, the post actions can let these values posted successfully through html input element without error. Even after I marked the controller action as [ValidateInput(true)]. How can I make them validate those post input?
Any advice will be appreciated!
Without seeing your GET handler, or what you're sending to it, it's tough to say why it behaves that way. However, OOTB MVC guards against SQL injection through the use of Entity Framework, and against XSS through ModelState validation.
Inside the body of your POST action that handles this forms submission you'll want to use code much like the following:
if (ModelState.IsValid)
{
//do the stuff I want to do when things are valid and free of XSS
}
else
{
//something went wrong. Probably shouldn't process this one. Have the user try again
}
Update: please disregard my filthy lies. ValidateInput(true) is not necessary because it is on by default. So, the only things I can think of would be that you have the AllowHtml attribute on your class or properties, or you are not posting back a model for modelBinding, and therefore input validation, to occur. At this point, you're probably going to need to put up some code for further help. There's too many unknowns right now.
I ran into a similar issue - we had JQuery using $.ajax to post JSON to the MVC action. The default model binder does not validate posted JSON allowing unsafe XSS to be posted against our action.
To solve this, I found the RequestValidator has a static method InvokeIsValidRequestString that allowed
public class ValidateJsonXssAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var request = filterContext.HttpContext?.Request;
if (request != null && "application/json".Equals(request.ContentType, StringComparison.OrdinalIgnoreCase))
{
if (request.ContentLength > 0 && request.Form.Count == 0) //
{
if (request.InputStream.Position > 0)
request.InputStream.Position = 0; // InputStream has already been read once from "ProcessRequest"
using (var reader = new StreamReader(request.InputStream))
{
var postedContent = reader.ReadToEnd(); // Get posted JSON content
var isValid = RequestValidator.Current.InvokeIsValidRequestString(HttpContext.Current, postedContent,
RequestValidationSource.Form, "postedJson", out var failureIndex); // Invoke XSS validation
if (!isValid) // Not valid, so throw request validation exception
throw new HttpRequestValidationException("Potentially unsafe input detected");
}
}
}
}
}
Then, you can just decorate relevant MVC actions expecting JSON-posted data that might bypass the standard XSS prevention:
[HttpPost]
[ValidateJsonXss]
public ActionResult PublishRecord(RecordViewModel vm) { ... }
You can see other options for customizing request validation with OWASP .NET recommendations by extending the RequestValidator object, which exposes the string validation done by the ValidateInput automatically utilized by MVC for other scenarios of query string, form collection, and cookie values.
For more info: https://www.owasp.org/index.php/ASP.NET_Request_Validation

How to send data from client to server using Rikulo stream

I'm trying to use Rikulo stream, and i have some trouble when i want to send data from client to server.
Suppose that i have a registration form and i want send a request to check if that username already exist in my database.
I have adopted MVC pattern, so i want that the controller received data and then, using a dao class, check if username exist or not.
In client side i have this lines of code
InputElement username = query('#username');
document.query("#submit").onClick.listen((e) {
HttpRequest request = new HttpRequest();
var url = "/check-existing-username";
request.open("POST", url, async:true);
request.setRequestHeader("Content-Type", "application/json");
request.send(stringify({"user": username.value}));
});
Is this the correct way to send data?
Here my server side code
void main(){
Controller controller = new Controller();
var _mapping = {
"/": controller.home,
"/home": controller.home,
"/check-existing-username" : controller.checkUsername
};
new StreamServer(uriMapping: _mapping).start();
And my controller method
void checkUsername(HttpConnect connect) {
//How to access data received from client?
}
The dao class is already defined, so i want only know how to access data.
I hope that someone can help me.
Since you're using POST, the JSON data will be in the HTTP request's body. You can retrieve it there. Rikulo Commons has a utility called readAsJson. You can utilize it as follows.
import "package:rikulo_commons/convert.dart";
Future checkUsername(HttpConnect connect) {
return readAsJson(connect.request).then((Map<String, String> data) {
String username = data["user"];
//...doa...
});
}
Notice that reading request's body is asynchronous, so you have to return a Future instance to indicate when it is done.

RedirecttoAction with error message

I have a link on a grid in my AdminUsers view
grid.Column(header: "", format: (item) => (condition ? Html.ActionLink("Impersonate", "Impersonate", "Admin", new { id = item.username }, null) : Html.Label("Impersonate"), style: "webgrid-column-link"),
In the controller, I have
public ActionResult Impersonate(string id)
{
string result = ORCA.utilities.users.setImpersonation(id);
if(result == "nocommonfields")
return RedirectToAction("AdminUsers", "Admin");
else
return RedirectToAction("terms_of_use", "Forms");
}
How can send an error message to display when I return to the AdminUsers page?
You may use TempData
if(result == "nocommonfields")
{
TempData["ErrorMessage"]="This is the message";
return RedirectToAction("AdminUsers", "Admin");
}
and in your AdminUsers action, you can read it
public ActionResult AdminUsers()
{
var errMsg=TempData["ErrorMessage"] as string;
//check errMsg value do whatever you want now as needed
}
Remember, TempData has very short-life span. Session is the backup storage behind temp data.
Alternatively, You may also consider sending a flag in your querystring and read it in your next action method and decide what error message to show.
The TempData controller property can be used to achieve this kind of functionality. Its main drawback in my opinion is that it uses the session storage in to store its contents. This means that you'll have extra work getting it to function on a web farm, or that you need to turn on sessions in the first place.
The good thing about TempData is that is exactly does what you want. Its a string based dictionary and you can put anything in it and by default get it out only once. So before calling RedirectToAction() you set your message. On the next request you check for messages and display them. By retrieving the messages they are automatically deleted at the end of the request.
As an alternative you could use cookies for transporting the message between the two requests. Essentially you could either roll your own solution, or implement a custom ITempDataProvider which transports the contents of TempData via cookies. Note that you need to properly secure cookies. MachineKey.Protect() can help you if you are rolling your own.
I was facing the same problem you did and created a solution for it called FlashMessage. Perhaps this could save you some work. It's available on NuGet as well. Usage is simple: you simply queue a message before you call RedirectToAction() as follows:
if(result == "nocommonfields")
{
FlashMessage.Warning("Your error message");
return RedirectToAction("AdminUsers", "Admin");
}
In your view you include the following statement to render any previously queued messages:
#Html.RenderFlashMessages()

Resources