I don't really have an idea how to use PUT method of web api passing the parameter from angular.
I understand how GET method executed but the PUT, POST and DELETE are really hard for me.
I read many articles but it i still dont get an idea
I have a code like this in controller in my web api:
static readonly IProfile profileRepository = new ProfileRepository();
[Route("api/profile/")]
[HttpGet]
[System.Web.Http.AcceptVerbs("GET")]
public IEnumerable<Profile> getProfiles()
{
return profileRepository.getProfiles();
}
[Route("api/profile/")]
[HttpPut]
[System.Web.Http.AcceptVerbs("PUT")]
public IEnumerable<Profile> putProfile(Profile profile)
{
profileRepository.putProfile(profile);
return getProfiles();
}
I also have like this in service in my angularJS
var _putProfile = function (name,address,contacts) {
return $http.put(serviceURL + 'api/profile/Name=' + name + '&Address=' + address + '&Contact=' + contacts).then(function (results) {
return results;
});
};
When i use Postman application the web api execute well when i use x-www-form-urlencoded and it passes data from postman to web api but how to pass data from angularJS to web api.
Is there anyone can give me a best answer here.. Please give me an idea how to do it and please advice me what is the best practice..
Im only new in angularJS and Web Api please guide me.. Thanks you so much
AngularJS send json data and not x-www-form-urlencoded format data. Web API has capability of reading both.
When it comes to HTTP PUT verb, data should be passed in body not query string.
For your $http.put call you should do something like this.
$http.put(serviceURL + 'api/profile', { Name:name, Address:address, Contact:contacts});
Please read $http documentation.
Related
I am asked to implement a REST Web API to a specific route, where either of two different Json Datatypes may be posted.
This results in the following exception being thrown:
Microsoft.AspNetCore.Routing.Matching.AmbiguousMatchException: The request matched multiple endpoints.
Is there an Attribute that can be placed on the Web Methods, referencing Properties of the Json payloads so as to disambiguate the two possible Datatypes?
This was covered here but I'll add a little bit.
It's not good API design to do that and goes against Swagger / OpenAPI specifications to do what you're asking.
The only way to do this with the same HTTP method (POST in your case) is to have one action that takes in both models. Check which one isn't null to then route to the correct method to handle that logic.
If you can get away with using a different HTTP verb you could technically do that and have two separate action methods (like POST and PUT), but you wouldn't be using them "correctly" and based on your question and need, I doubt you can do that anyway.
You can read the request body as a string and then try to decide which type to deserialize in:
[HttpPost]
[Route("api/mypath")]
public async Task<IActionResult> MyMethod()
{
request.Body.Position = 0;
var reader = new StreamReader(request.Body, Encoding.UTF8);
var body = await reader.ReadToEndAsync();
if(body.Contains("A))
{
var A = JsonConvert.DeserializeObject<A>(body);
}
else{
var B = JsonConvert.DeserializeObject<B>(body);
}
}
And add a middleware to enable request buffering:
app.Use(next => context => {
context.Request.EnableBuffering();
return next(context);
});
You can read more about it here
I have two different web application in which i have logged in one of them.Now I want to pass those login credentials to the second web application and to do log in without a click.
what will be the secure and convenient way to do this. And what important modifications are needed on two simple login pages. Both of the project are being handled by the same database.
any suggestion is welcome.
You can use WebApi for any third party to get access to your application. WebApi works as an end point. Here is the basic sample/syntax.
// GET /api/customers
public IHttpActionResult GetCustomers()
{
var customerDtos = _context.Customers
.Include(c => c.MembershipType)
.ToList()
.Select(Mapper.Map<Customer, CustomerDto>);
return Ok(customerDtos);
}
For POST
// POST /api/customers
[HttpPost]
public IHttpActionResult CreateCustomer(CustomerDto customerDto)
{
if (!ModelState.IsValid)
return BadRequest();
var customer = Mapper.Map<CustomerDto, Customer>(customerDto);
_context.Customers.Add(customer);
_context.SaveChanges();
customerDto.Id = customer.Id;
return Created(new Uri(Request.RequestUri + "/" + customer.Id), customerDto);
}
In order to check if your api end point is working properly, You can download Chrome Extension "ARC" - Advanced Rest Client. Using this you can test the API end point and it's output. You do no need a third party full fledged app to test the end point.
How do you properly create a Web API POST of complex object or multiple parameters using Angular2?
I have a service component in Angular2 as seen below:
public signin(inputEmail: string, inputPassword: string): Observable<Response> {
return this.http.post('/api/account/signin', JSON.stringify({ Email: inputEmail, Password: inputPassword}), this.options);
}
The targeted web api is seen below:
[HttpPost]
[Route("signin")]
public async Task<IActionResult> Signin(string email, string password)
{
....
}
This does not work because I need to convert the parameters of the web api into a single POCO class entity with Email and Password properties and put the [FromBody] attribute: Signin([FromBody] Credential credential)
Without using [FromURI] (POST requests with query strings?), how can I make POSTs of multiple parameters or complex objects without converting these parameters into a single POCO class?
Because what if I have numerous Web API POST actions with parameters like (string sensitiveInfo1, string name, int sensitiveInfo2) or (ClassifiedInfo info, string sensitiveInfo1, string sensitiveInfo2), do I need to convert them all to POCO classes and always use [FromBody]?
PS.
I was using RestangularJS before and it can posts anything (mulitple primitive objects and complex objects) without my Web API actions having [FromBody] attributes. Will about to investigate how RestangularJS do it.
Without using [FromURI] (POST requests with query strings?), how can I make POSTs of multiple parameters or complex objects without converting these parameters into a single POCO class?
I know its not what you want to hear but out of the box this is not possible. It is not a limitation of the browser code that is making the request. This means it does not matter if you are using Angular, JQuery, straight JavaScript, or even RestangularJS. This is a limitation (I use that word loosely as I am sure this is by design) of Web API (any version). Here is the documentation on this design: Parameter Binding in ASP.NET Web API by Mike Wasson.
At most one parameter is allowed to read from the message body. So this will not work:
// Caution: Will not work!
public HttpResponseMessage Post([FromBody] int id, [FromBody] string name) { ... }
So the question becomes, what are your options?
Create a model
This is the thing you were trying to avoid but I list it first because this is how Web API was intended to behave. I have not yet heard a compelling reason not to do this. This approach allows you to extend your model easily without having to change the method signature. It also allows for model validation on the model itself. Personally I really like this approach.
public class SignInModel{
public string Email {get;set;}
public string Password {get;set;}
}
[HttpPost]
[Route("signin")]
public async Task<IActionResult> Signin(SignInModel signInModel)
{
// ....
}
I did not repeat your existing JavaScript code because what you have works as is with the above web api code
URL
Again, what you were trying to avoid. This does make what you want possible with the limitation that you have to pass these parameters using the Query string on the URL. The JavaScript would change but the signature you had on the Web API method would not.
public signin(inputEmail: string, inputPassword: string): Observable<Response> {
return this.http.post('/api/account/signin/?email=inputEmail&password=inputPassword', null, this.options);
}
I did not repeat your existing Web API code because what you have works as is with the above web JavaScript code (by default FromUri is assumed I believe)
Custom Model Binder
See Passing multiple POST parameters to Web API Controller Methods by Rick Strahl. This option allows you to create a custom model binder that could do what you are asking. It is a whole bunch of extra code though for, IMHO, not much benefit. Maybe there are situations where it would be useful although I really cannot think of any off the top of my head.
Dynamic
Finally you could also pass in a dynamic object as the parameter of your Web API. This is essentially the same as receiving the JSON as a string and making your Controller code responsible for the deserialization of content. Again, I believe that this would make your code worse in most situations as you have to implement custom validation and type checks. This answer was proposed previously on SO by Bes Ley. Again, maybe there are situations where it would be useful although I really cannot think of any off the top of my head.
If you call Web API 2.2 post method from Angular 2 type script, dont forget to add following header content and parameter object.
let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
var params = new URLSearchParams();
params.set('userid', '102');
params.set('username', 'foo');
return this._http.post('http://localhost:6579/api/PostUser', params.toString(), { headers: headers }).map(res => res.json());
Perhaps you should post with options:
{
headers: new Headers({
'Content-Type': 'application/x-www-form-urlencoded'
})
}
and encode data like
jQuery.param({user:'bla', password: 'bla'});
WebAPI does not provide this out of the box. If you try to get understanding of web API bindings, you might be able to figure out why.
I think this article might help.
The generic rules are:
– simple, string-convertible parameters (value types, strings, Guids, DateTimes and so on) are by default read from URI
– complex types are by default read from the body
– collections of simple parameters are by default read from the body too
– you cannot compose a single model based on input from both URI and request body, it has to be one or the other
I have fixed the issue of Angular2 HTTP Post ASP.NET MVC Web API
let headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8');
let params: URLSearchParams = new URLSearchParams();
params.set('value', '2');
let options = new RequestOptions({
headers: headers//,
//search: params
});
let content = new URLSearchParams();
content.set('StudentName', 'Inderjit Singh';
content.set('Mobile', '+919041165398');
content.set('Nationality', 'Indian');
content.set('AdmissionNo', '6');
content.set('SectionCode', '1');
content.set('Gender', 'Male');
content.set('RegNo', '18585');
content.set('ClassCode', '1');
this.http.post('YOUR_URL', content.toString(), { headers: headers }).map((res: Response) => { console.log("data is==>" + res.text()); }).subscribe();
WebApi will be able to deserialize your Credential object provided the JSON object has the same field names (I am not sure about case so you may be right here). You seem to be missing the headers from the post call in your Angular2 component.
Can you check the Content-Type using Chrome Debugger or Fiddler? It should be application/json.
Try this, passing a complex class object into a single data parameter.
var SearchQuery = function () {
this.Alphabet = null;
this.Search = false;
this.Keyword = null;
this.RegionList = null;
};
var para = new SearchQuery();
{ data: JSON.stringify(para) } - Post Data
you can receive it using a JObject in your API controller and deserialize it as according to your classes.
I have settings in AppSettings (web.config) and I need to pass them to an external javascript file.
In ASP.NET I would think of an ASHX handler to write the javascript file to the response replacing placeholders with the settings values.
Is there a better way to do it in ASP.NET MVC? Thank you.
You could send them via a JsonResult?
In your JS, you'd have a request which sends a GET/POST request to a particular action (let's call it GetAppSetting(), and the corresponding value is returned in the response.
For security reasons, I would restrict what can be requested though...
public JsonResult GetAppSetting(string id)
{
//You could check what's been requested here if you want to make sure you're only returning information that you may not wish to send.
string appSetting = AppSettings[id];
if(string.IsNullOrEmpty(appSetting) == false)
{
return Json(appSetting, JsonRequestBehavior.AllowGet);
}
//Handle non-existent settings here...
throw new Exception("This setting does not exist");
}
Alternatively, it has been suggested by Chris Marisic in the comments that you may want to absolutely limit this to just a specific set of key/values for developer reasons. Therefore, here is a quick example of that...
public JsonResult GetAppSettings()
{
var appSettings = new Dictionary<string, string>();
appSettings.Add("myAppSetting1", AppSettings["myAppSetting1"]);
appSettings.Add("myAppSetting2", AppSettings["myAppSetting2"]);
appSettings.Add("myAppSetting3", AppSettings["myAppSetting3"]);
return Json(appSettings, JsonRequestBehavior.AllowGet);
}
Note the JsonRequestBehavior.AllowGet in the JsonResults (MVC 2 only). This is because, by default, ASP.NET MVC 2 will not allow GET requests on actions which return a JsonResult. You can circumvent this by adding the JsonRequestBehaviour, but I should probably mention that you should consider doing a post request in order to retrieve this information, and remove this behaviour in your action.
I’m about to start work on an OpenRasta project (an xml over http web service). OpenRasta looks great but unfortunately worked examples seem few and far between on the internet. Looking at the test side of the project, if my handlers are returning strongly typed objects (not OperationResult), i.e.:
public class PersonHandler
...
public Person Get(int id)
{
...
How can I test for http status codes? (For example if the handler throws an uncaught exception). I’m not sure what level the tests pitch in at, and what needs mocking (using moq btw)
Any help appreciated, particularly coded examples!
I faced the same problem, and ended up writing my tests as integration tests at a much higher level, actually making real REST/HTTP calls through a simple HttpWebRequest client. This allowed me to check the HTTP response headers / status codes and double-check the JSON/XML serialization from the client's perspective, which was just as important as whether or not the operations succeeded.
I started by returning OperationResult from all my handlers, and used these to wrap the strongly-typed objects. My handlers all inherit from a base class with a few helper methods that make it easier to return a custom error with a user-friendly error message. The more I coded this up, the more my handlers resembled a ASP.NET MVC controller. e.g.:
public OperationResult GetById(int id)
{
try
{
// do stuff here
return OKResult( // some strongly-typed resource );
}
catch(SomeException ex)
{
return BadRequestResult(SomeErrorCode, ex.Message);
}
}
Then in the test client, it's pretty easy to just check the HTTP status code. Obviously this doesn't help much with mocking. I'm not sure what the best solution is, in fact I've favorited this question in the hope that someone answers it better than I can - but this has worked pretty well for me so far.
The handler is just a class--ideally with minimal dependencies--so your unit tests can just test the isolated logic in the class.
If you want to test for status codes, I recommend (based on very little experience!) using OpenRasta self-hosting.
Here's a test (somewhat changed) that I wrote recently:
[TestMethod]
public void POST_with_inaccurate_contentLength_returns_405()
{
var resource = GetResource();
IRequest request = new InMemoryRequest
{
HttpMethod = "POST",
Uri = new Uri("http://localhost/Resource"),
};
request.Headers.ContentLength = 16; //wrong!
request.Entity.Stream.Write(resource.Content, 0, resource.Content.Length);
var response = _host.ProcessRequest(request);
Assert.AreEqual(405, response.StatusCode);
}
I should add that the host is set up in the TestInitialize method as such:
_host = new InMemoryHost(new Configuration());
_host.Resolver.AddDependencyInstance(typeof(IFileResourceRepository), _repository, DependencyLifetime.Singleton);
...and is cleaned up in the TestCleanup method.