I have Post Method
[HttpPost]
public HttpResponseMessage Post(MemberViewModel model)
Another Post Method in same Controller. I add the attribute routing in login method
[Route("api/members/login")]
[HttpPost]
public HttpResponseMessage Login([FromBody]LoginViewModel model)
{}
public class LoginViewModel
{
public string UserName { get; set; }
public string Password { get; set; }
}
The default post method is working fine but
when I call Login Post Method the model (LoginViewModel is always null). I used fiddler to do the testing.
Fiddler
POST http://localhost:49595/api/members/login/ Http/1.1
User-Agent: Fiddler
Content-Type: Application/JSON
Host: localhost:49595
Content-Length: 79
Request Body
{
“Username”: customer#gmail.com,
“Password”: “393f83x393”
}
It is working fine with one parameter
[Route("api/members/login")]
[HttpPost]
public HttpResponseMessage Login([FromBody]string userName)
{}
Kindly advice what wrong with Model
Thanks.
Your Fiddler shows this line:
Request Body { “Username”: customer#gmail.com, “Password”: “393f83x393” }
That's not valid JSON. The email account should be enclosed in single or double quotes.
Related
I have a web api for which i would need to implement custom authentication and authorization. The authorization should be defined by Resource and Action as shown below:
[Authorize("users","view")]
public async Task<IHttpActionResult> GetAsync()
{
}
Is there any way i can use custom authorization filter and implement this?
Also, the web api is protected by client certificate and the caller is identifier by key which is passed in the request header. The Key is authenticated using a custom authentication filter.
Regarads,
John
Yes you can create custom Authorization and put on controller or method that needs to be authorized.
sample example is as below
public class CustomAuthorize : System.Web.Http.AuthorizeAttribute
{
private string Resource { get; set; }
private string Action { get; set; }
public CustomAuthorize(string resource, string action)
{
Resource = resource;
Action = action;
}
public override void OnAuthorization(
System.Web.Http.Controllers.HttpActionContext actionContext)
{
base.OnAuthorization(actionContext);
//Check your post authorization logic using Resource and Action
//Your logic here to return authorize or unauthorized response
}
}
Here you can do your custom authorization logic and sample controller will look like this
public class DoThisController : ApiController
{
[CustomAuthorize("users","view")]// for specific methods
public string Get()
{
return "Sample Authorized";
}
}
I have a controller with the default post method. I want to add one more with a different name and action. The problem is when I make the request POST (http://localhost:57926/api/Users/Login) it doesn't execute Login method, it executes the default PostUser method.
How can I fix this?
// POST: api/Users
[ResponseType(typeof(User))]
public IHttpActionResult PostUser(User user){
//Some code
}
[HttpPost]
[Route("Login")]
public IHttpActionResult Login(JObject form)
{
//some code
}
I have the following simple HTTPPOST endpoint;
[AllowAnonymous]
[HttpPost]
[Route("forgotPassword")]
public IHttpActionResult ForgotPassword(string userName, string callbackUrl)
Where the controller is decorated as follows;
[Authorize]
[RoutePrefix("api/accounts")]
public class AccountsController : ApiController
Now when i try to test this endpoint in postman, using the following url;
http://localhost:11217/api/accounts/forgotPassword
with the strings in the body of the message
I get the following return.
{ "Message": "No HTTP resource was found that matches the request
URI 'http://localhost:11217/api/accounts/forgotPassword'.",
"MessageDetail": "No action was found on the controller 'Accounts'
that matches the request." }
Now I would rather not have to create a model for the two strings (if possible). Also if I try to put the params in the query string I get a potantially dangerous request response
http://localhost:11217/api/accounts/forgotPassword/test&callbackUrl=local
Can anyone help please?
If you want to send mulitple parameters when doing a post request you should create a DTO that contains the parameters as
public class forgetPasswordDTO
{
public string userName { get; set; }
public string callbackUrl { get; set; }
}
Then add the DTO as a method parameter with the [FromBody]
[AllowAnonymous]
[HttpPost]
[Route("forgotPassword")]
public IHttpActionResult ForgotPassword([FromBody] forgetPasswordDTO data)
And in you client, create the object as
var data = {
'userName': user,
'callbackUrl': url
};
And add it to the body of the request.
Here's a nice article about this topic
I am trying to get a web api call to work: I want to submit an email address and then on the server, the method will validate and return null or a message.
This is what I tried:
[Post]
public string validate(string email) {
return this._contextProvider.ValidateEmail(email);
}
However, I get this message returned to the client: No HTTP resource was found that matches the request URI 'https://localhost:44300/breeze/data/validate
The payload looks like this: {email: "Greg#gmail.com"}
The problem, it turns out, was the parameter binding.
In the Web API, binding is handling differently than MVC. By default, simple types are extracted from the URI, not the body. Complex types are extracted from the body of the message.
I then added the [FromBody] Attribute to the Action Method, and it then found the action method. But alas, the email parameter was null.
public string validate([FromBody]string email) {
return this._contextProvider.ValidateEmail(email);
}
Turns out when using this trick, the body must NOT be json, but constructed like a querystring - email=greg#gmail.com. I didn't want do do that, so ended up creating a class to accept the parameter, and that worked as expected.
public class ParameterizedAction {
public string Parameter { get; set; }
}
public string validate(ParameterizedAction arg) {
return this._contextProvider.ValidateEmail(arg.Parameter);
}
This article has more info: http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-and-action-selection
as well as this one: http://encosia.com/using-jquery-to-post-frombody-parameters-to-web-api/
Here are my Entities. I am using entity framework code first.
public class Trade
{
public Guid Id { get; set; }
[MaxLength(10)]
public string AssetClass { get; set; }
public TradeBatch Batch { get; set; }
}
public class TradeBatch
{
public TradeBatch()
{
StartedOn = DateTime.Now;
}
public Guid Id { get; set; }
public DateTime StartedOn { get; set; }
public List<Trade> Trades { get; set; }
}
In My Controller I have:
[AcceptVerbs("PATCH")]
public void UpdateTrade(Guid id, Delta<Trade> update)
{
var tradeToUpdate = _repTradeService.GetRepTradeById(id);
update.Patch(tradeToUpdate);
_repTradeService.SaveChanges();
}
When I Make a request (using fiddler), update is null.
Here is the patch Request:
PATCH http://localhost:61579/api/RepTrades/4e43b48a-a4fd-4ffc-841d-08dac55deb60 HTTP/1.0
User-Agent: Fiddler
Host: localhost:61579
Content-Length: 55
Content-Type: application/json
{"AssetClass":"Test"}
The value for "Update" in the Patch Action is always null. Any pointers to why?
You may want to try setting the content-type header to application/json;odata=verbose
I would have just commented but don't have the reputation yet.
Your JSON is fine, and the method should accept it as far as I can see. You can see what the exact error is by adding the following line of code at the top of your PATCH method:
if (!ModelState.IsValid) {
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState));
}
This way, if your JSON is not valid according to the model the method is expecting, it returns a HTTP 400 Bad Request message, along with the ModelState. The message of that response will contain the reason why the ModelState is not valid.
In my case the answer from #kazu helped me find the problem because it gave me a break point where the debugger could reveal the problem.
I had a setter in my class, which was trying to set a property on an object which had not been initialised. By breaking with the debugger on the "throw" command, I was able to see the stack trace in the properties of the ModelState object, and the stacktrace said my setter on a particular field was throwing "Object Reference Not Set". With that I could immediately see the problem.
My object was like this:
public MyObject
{
private PrivateObjectType _privateObject;
public MyObject()
{
}
public string myProperty
{
get { return _privateObject.myProperty; }
set { _privateObject.myProperty = value; }
}
}
So obviously I needed to put this in the constructor:
_privateObject = new PrivateObjectType();