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.
Related
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.
How to set session attributes in restassured? In my application code we have something like this
String userId= request.getSession().getAttribute("userid")
How to set userId as session attribute here(in restassured test case)?
How to maintain the same session for all the requests(multiple subsequent requests)?
When i send multiple requests, it's considering every request as new and session is getting invalidated from server side, i want to maintain session between subsequent calls.
I tried setting jsessionid in the cookie and sent it in the second request, but when i debugged in the server side, it's not loading the session which was created, instead it's creating different session and because of this its doesn't show the attribute which i have set in the session when i first sent the request.
When i tried the same with direct HttpClient, it working, where as the same with RestAssured it's not working.
Code which was working with HttpClient is this
HttpClient httpClient = util.getHttpClient();
//1st request
HttpResponse response=httpClient.execute(postRequest);
from response i have extracted the jessionid and set this in the second request
HttpGet getRequest = new HttpGet(Client.endPointUrl);
getRequest.addHeader("content-type", "application/json");
getRequest.addHeader("accept", "application/json");
getRequest.addHeader("Origin", Client.endPointUrl);
getRequest.addHeader("Referer", Client.endPointUrl);
getRequest.addHeader("Auth-Token", authToken);
getRequest.addHeader("Set-Cookie", jsessionId);
//2nd request after setting the jessionid which i have extracted from the response
HttpResponse eventsResponse = httpClient.execute(getRequest);
Above code is working perfectly fine and i am getting expected response. One observation is i am using the same httpClient Object for invoking both the requests.
Where as i if i try the same using RestAssured, it's not working.
RestAssured.baseURI = "http://localhost:8080";
Response response=RestAssured.given().header("Content-Type","application/json").
header("Origin","http://localhost:8080").
header("Referer","http://localhost:8080").
body("{"+
"\"LoginFormUserInput\":{"+
"\"username\":\"test\","+
"\"password\":\"password\""+
"}"+
"}")
.when().post("/sample/services/rest/validateLogin").then().extract().response();
JsonPath js=Util.rawToJson(response);
String sessionId=js.get("sessionID");
System.out.println(sessionId);
for (Header header:response.getHeaders()) {
if ("Set-Cookie".equals(header.getName())) {
id= header.getValue().split(";")[0].trim();
String[] arr=jsessionId.split("=");
jsessionId=arr[0];
break;
}
}
response=RestAssured.given().header("Auth-Token",sessionId).header("Content-Type","application/json").
cookie("JSESSIONID",jsessionId).
header("Origin","http://localhost:8080").
header("Referer","http://localhost:8080").
body("{}").
when().
post("/sample/services/rest/getAllBooks").then().contentType("").extract().response();
I tried reusing the same httpclient for all the requests using the following, but it didn't work
RestAssured.config = RestAssured.config().httpClient( new HttpClientConfig().reuseHttpClientInstance());
You need to use Session filter in Rest Assured
https://github.com/rest-assured/rest-assured/wiki/Usage#session-support
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.
My server side breeze api calls require me to validate the token value provided with each call before returning any data. To achieve this, i am passing TokenId with each Entity Query using withParameters function of breeze Entity Query and specify the parameter on my server side controller action as illustrated below.
Following is how i am doing it right now:
Client Side
function GetCustomers(){
return breeze.EntityQuery.from('Customers')
.withParameters({ TokenId: 'token value' })
.using(entityManager).execute()
}
Server Side
[HttpGet]
public IQueryable<Customer> Customers(string TokenId)
{
//server side logic
}
This for some reason looks to me can be simplified using some configuration on Breeze Entity Manager which automatically adds the parameter value to every query sent from client. And also, on server side, i don't think its necessary to have tokenId parameter defined on each controller method. This should be easy to solve with Action Filters on the server side.
Can someone point me in right direction if it is possible and how to do this?
Thanks
You should always pass custom authentication information, such as tokens, in the headers.
If you can pass it as a custom header you can search for 'define custom headers breeze.js' to see how that can be done.
A good example -
http://breeze.github.io/doc-js/server-ajaxadapter.html
Also keep in mind that if you put the token in the query string that is persisted by most of the servers that your call is crossing over, making it much easier to find tokens for your application if an evil-doer were to download the logs from that server.
Also keep in mind that if you are using cross-domain requests (CORS) you will need to enable the custom header on the server side that is receiving the call.
To give an example of the answer above:
// get the current default Breeze AJAX adapter
var ajaxAdapter: any = breeze.config.getAdapterInstance('ajax');
// set fixed headers
ajaxAdapter.defaultSettings = {
headers: {
"Bearer": this.bearerToken
}
};
Note also that if you are using ASP.net Identity (which includes a cookie based authentication), you must include this code so that the asp.net pipeline does NOT use that cookie:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Filters.Add(new Ask.Filters.RequireHttpsAttribute());
//This forces http header authentication which is required for web api calls.
config.SuppressDefaultHostAuthentication();
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
Note also that you should use only https, with this filter:
public class RequireHttpsAttribute : AuthorizationFilterAttribute
{
public int Port { get; set; }
public RequireHttpsAttribute()
{
Port = 443;
}
public override void OnAuthorization(HttpActionContext actionContext)
{
var request = actionContext.Request;
if (request.RequestUri.Scheme != Uri.UriSchemeHttps)
{
var response = new HttpResponseMessage();
if (request.Method == HttpMethod.Get || request.Method == HttpMethod.Head)
{
var uri = new UriBuilder(request.RequestUri);
uri.Scheme = Uri.UriSchemeHttps;
uri.Port = this.Port;
response.StatusCode = HttpStatusCode.Found;
response.Headers.Location = uri.Uri;
}
else
{
response.StatusCode = HttpStatusCode.Forbidden;
}
actionContext.Response = response;
}
else
{
base.OnAuthorization(actionContext);
}
}
}
And finally, make sure you use the [Authorize] and [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)] attribute on your controllers.
See the Full Sample and article on asp.net
I suggest using oAuth tokens in the header. I am currently using Auth0, but there are many others including Google Firebase. BreezeJS has been expanded such that it will accept AuthHttp as it's HTTP client for all calls. AuthHttp will automatically add a bearer token to the header of every call to the server.
One the server side it's a matter of adding the proper oAuth client lib (via Nuget) which automatically parses out the bearer token, validates it against the oAuth server, and makes claims available for use within your API call.
For example, in my implementation my api code will receive a claim that contains the users id, which I can then validate against my db and use to filter all actions. This keeps user B from loading user A's data by directly calling the api in a browser.
For example, all API calls are first validated by the oAuth subsystem. Once my api code is executed I know the caller has been validated and I use the passed claims (user id) to access only the calling users data - REGARDLESS what was actually requested by the API call parameters (which can be forged as easily as editing a URL string).
A simple example of this would be exposing your UserSet in the API. If you don't filter by the user claim id you must realize that every user in your system will be accessible by constructing a simple URL in a browser.
Here I filter out and return only the user record identified by the user id in the auth claim. Note I use #if AUTH simply for testing as PROD will always have AUTH turned on.
#if AUTH
[Authorize]
#endif
[HttpGet]
[EnableBreezeQuery(MaxExpansionDepth = 5)]
public IQueryable<User> UserSet()
{
#if AUTH
Guid guid = userGuid();
return _efContext.Context.UserSet.Where(x => x.active && x.guid == guid);
#else
return _efContext.Context.UserSet;
#endif
}
All of this sounds complicated, but it really is quite easy to implement.
Thanks,
Mike
I've been trying to get the GetClientAccessToken flow to work with the latest release 4.1.0 (via nuget), where I'm in control of all three parties: client, authorization server and resource server.
The situation I have started to prototype is that of a Windows client app (my client - eventually it will be WinRT but its just a seperate MVC 4 app right now to keep it simple), and a set of resources in a WebAPI project. I'm exposing a partial authorization server as a controller in the same WebAPI project right now.
Every time (and it seems regardless of the client type e.g. UserAgentClient or WebServerClient) I try GetClientAccessToken, by the time the request makes it to the auth server there is no clientIdentifier as part of the request, and so the request fails with:
2012-10-15 13:40:16,333 [41 ] INFO {Channel} Prepared outgoing AccessTokenFailedResponse (2.0) message for <response>:
error: invalid_client
error_description: The client secret was incorrect.
I've debugged through the source into DNOA and essentially the credentials I'm establishing on the client are getting wiped out by NetworkCredential.ApplyClientCredential inside ClientBase.RequestAccessToken. If I modify clientIdentifier to something reasonable, I can track through the rest of my code and see the correct lookups/checks being made, so I'm fairly confident the auth server code is ok.
My test client currently looks like this:
public class AuthTestController : Controller
{
public static AuthorizationServerDescription AuthenticationServerDescription
{
get
{
return new AuthorizationServerDescription()
{
TokenEndpoint = new Uri("http://api.leave-now.com/OAuth/Token"),
AuthorizationEndpoint = new Uri("http://api.leave-now.com/OAuth/Authorise")
};
}
}
public async Task<ActionResult> Index()
{
var wsclient = new WebServerClient(AuthenticationServerDescription, "KieranBenton.LeaveNow.Metro", "testsecret");
var appclient = new DotNetOpenAuth.OAuth2.UserAgentClient(AuthenticationServerDescription, "KieranBenton.LeaveNow.Metro", "testsecret");
var cat = appclient.GetClientAccessToken(new[] { "https://api.leave-now.com/journeys/" });
// Acting as the Leave Now client we have access to the users credentials anyway
// TODO: CANNOT do this without SSL (turn off the bits in web.config on BOTH sides)
/*var state = client.ExchangeUserCredentialForToken("kieranbenton", "password", new[] { "https://api.leave-now.com/journeys/" });
// Attempt to talk to the APIs WITH the access token
var resourceclient = new OAuthHttpClient(state.AccessToken);
var response = await resourceclient.GetAsync("https://api.leave-now.com/journeys/");
string sresponse = await response.Content.ReadAsStringAsync();*/
// A wrong one
/*var wresourceclient = new OAuthHttpClient("blah blah");
var wresponse = await wresourceclient.GetAsync("https://api.leave-now.com/journeys/");
string wsresponse = await wresponse.Content.ReadAsStringAsync();
// And none
var nresourceclient = new HttpClient();
var nresponse = await nresourceclient.GetAsync("https://api.leave-now.com/journeys/");
string nsresponse = await nresponse.Content.ReadAsStringAsync();*/
return Content("");
}
}
I can't figure out how to prevent this or if its by design what I'm doing incorrectly.
Any help appreciated.
The NetworkCredentialApplicator clears the client_id and secret from the outgoing message as you see, but it applies it as an HTTP Authorization header. However, HttpWebRequest clears that header on the way out, and only restores its value if the server responds with an HTTP error and a WWW-Authenticate header. It's quite bizarre behavior on .NET's part, if you ask me, to suppress the credential on the first outbound request.
So if the response from the auth server is correct (at least, what the .NET client is expecting) then the request will go out twice, and work the second time. Otherwise, you might try using the PostParameterApplicator instead.