I have a webapi controller and following is a post method.
public HttpResponseMessage Register(string email, string password)
{
}
How do I test from the browser?
When I test it from the browser with the following , it is not hitting the controller.
http://localhost:50435/api/SignUp/?email=sini#gmail.com&password=sini#1234
It is giving me the below error.
Can't bind multiple parameters ('id' and 'password') to the request's
content.
Can you please help me???
You get an error, because you cannot pass multiple parameter to WebApi in this way.
First option:
You can create a class and pass data through from body in this way:
public class Foo
{
public string email {get;set;}
public string password {get;set;}
}
public HttpResponseMessage Register([FromBody] Foo foo)
{
//do something
return Ok();
}
Second Option:
public HttpResponseMessage Register([FromBody]dynamic value)
{
string email= value.email.ToString();
string password = value.password.ToString();
}
And pass json data in this way:
{
"email":"abc#test.com",
"password":"123#123"
}
Update:
If you wan to get data from URL, then you can use Attribute Routing.
[Route("api/{controller}/{email}/{password}")]
public HttpResponseMessage Register(string email, string password)
{
//do something
return Ok();
}
Note:
URL should be : http://localhost:50435/api/SignUp/sini#gmail.com/sini#1234
Don't forget to enable attribute routing in WebApiConfig
If you use this way, you will have security issue.
Related
I created an asp.net core empty project and whenever I am trying to run my application it gives me the error shown below. I cannot even hit the end point as soon I hit play it gives the error.
System.InvalidOperationException
HResult=0x80131509
Message=Body was inferred but the method does not allow inferred body parameters.
Below is the list of parameters that we found:
Parameter | Source
---------------------------------------------------------------------------------
ur | Service (Attribute)
userLogin | Body (Inferred)
Did you mean to register the "Body (Inferred)" parameter(s) as a Service or apply the [FromService] or [FromBody] attribute?
No idea why I am getting this error. I then tried adding [FromService] and it says the same error as well. I read this article for the same issue but it says do not add [Bind] which I was not in the first place and to instead use [FromService] but I still get the same error. Is there something wrong I am doing?
Program.cs:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<ApplicationDbContext>(x =>
x.UseSqlServer(builder.Configuration.GetConnectionString("Default")));
builder.Services.AddScoped<IUserRepository, UserRepository>();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.MapGet("/userLogin", (IUserRepository ur, UserLogin userLogin) =>
{
return ur.Get(userLogin);
});
if (app.Environment.IsDevelopment())
{
app.UseSwagger(x => x.SerializeAsV2 = true);
app.UseSwaggerUI();
}
app.Run();
UserLogin:
[Keyless]
public class UserLogin
{
public string Username { get; set; }
public string Password { get; set; }
}
UserRepository:
public User Get(UserLogin userLogin)
{ // get the username and password make sure what was entered matches in the DB then return the user
var username =_dbContext.Users.Find(userLogin.Username, StringComparison.OrdinalIgnoreCase);
return username;
}
The exception message is telling you the problem:
Body was inferred but the method does not allow inferred body
parameters
The binder has inferred the UserLogin parameter as a parameter from the body, but inferred body parameters are not allowed.
The simplest way to get this working is to add [FromBody] attribute to the UserLogin parameter, however, in that case you should really change the method to POST since GET requests don't have a body.
app.MapPost("/userLogin", (IUserRepository ur, [FromBody]UserLogin userLogin) => {...}
Unfortunately, it's not possible to bind complex objects from query string values using [FromQuery] attribute in minimal APIs so your best option IMO is to use [FromBody] and MapPost.
If you need to use MapGet there is a work-around by adding a static BindAsync method to your UserLogin class - more details can be found in this blog post. Another alternative is to pass HttpContext to the action and take the values from the context - see this similar answer for binding [FromForm] - you'd use ctx.Request.Query["username"] to get the username from the HttpContext.
In my case I forgot to add the below to my program.cs file above my app.Run();
builder.Services.AddScoped<IUserRepository, UserRepository>();
Been long but from what I've checked.NET 6 wont let You specify model parameters without FromBody attribute but only for verbs that shouldnt base on model anyway, like DELETE or GET. You can in fact write POST/PUT requests without specyfing bind attributes thou.
Wont work:
app.MapDelete("/", (SomeModel model) => ...)
app.MapGet("/", (SomeModel model) => ...)
Will work:
app.MapPost("/", (SomeModel model) => ...)
app.MapPut("/", (SomeModel model) => ...)
Since you want to use MapGet, you'll need to add a BindAsync method to the UserLogin class
public class UserLogin
{
public string Username { get; set; }
public string Password { get; set; }
public static ValueTask<UserLogin> BindAsync(HttpContext context)
{
var result = new UserLogin
{
Username = context.Request.Query[nameof(Username)],
Password = context.Request.Query[nameof(Password)],
};
return ValueTask.FromResult(result);
}
}
I'm struggling with something very basic. I'm trying to be get a response from my WebApi2 restful service, and I can't.
I have not edited the default WebApi (WebApiConfig.cs) route.
This is the controller
public class AboutController
{
[Route("api/about/{id:int}/{service1}/{service2}")]
public async Task<IHttpActionResult> Get(int accountId, string mainservice, string secondaryservice)
{
//logic
}
}
If I navigate (in a browser) to http://localhost:58090/api/about I get the error message The requested resource does not support http method 'GET'. I guess this makes sense, as it doesn't match the route (path).
If I update the path to something which matches the signature, such as http://localhost:58090/api/about/1/a/b I get the error message No action was found on the controller About' that matches the request.
Even if I add [HttpGet] to the controller, it makes no difference.
As a sanity test, I updated to
public class AboutController
{
public async Task<IHttpActionResult> Get()
{
//logic
}
}
and it does what is expected. I'm lost as to why adding the parameters has confused things so much.
I'm lost as to what I've done wrong
The route must match the parameters
[Route("api/about/{id:int}/{service1}/{service2}")]
public async Task<IHttpActionResult> Get(int id, string mainService, string secondaryService)
{
The above won't work, because it is expecting to see service1 and service2 based upon the route.
Update as per the example below
[Route("api/about/{id:int}/{service1}/{service2}")]
public async Task<IHttpActionResult> Get(int id, string service1, string service2)
{
I am trying to upload a file and also JSON body at the same time to a POST method as below
public async Task<ResponseModel<PersonWriteResponse>> AddPerson([FromForm]IFormFile file, [FromForm]PersonPostRequest request)
{
var person = await _service.AddPerson(file,request);
return ResponseModelHelper.BuildResponse(person, $"/production/person", "person");
}
Both parameters are always null. In postman, I am specifying the content-type as "Multipart/form-data"
Is this the correct way of passing file and json data?
Alan-
I try to use model witch include IFormFile, and it's works
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> update([FromForm]MyFile model)
{
return Ok("Success!");
}
public class MyFile
{
public string Id { get; set; }
public IFormFile File { get; set; }
// Other properties
}
PostMan request here
You may set breakPoint at the return Ok("Success!"); line and saw what you get
I'm confused... I have a very simple Web API and controller, which works fine if I have a GET request, but 404's if I have a POST request.
[RoutePrefix("api/telemetry/trial")]
public class LoginTelemetryController : ApiController
{
[Route("login")]
[HttpPost]
public IHttpActionResult RecordLogin(string appKey) {
using (var context = new Core.Data.CoreContext()) {
context.ActivityLogItems.Add(new Domain.Logging.ActivityLogItem()
{
ActivityType = "Trial.Login",
DateUtc = DateTime.UtcNow,
Key = new Guid(appKey)
});
context.SaveChanges();
}
return Ok();
}
When I post against this in postman, I get:
{
"message": "No HTTP resource was found that matches the request URI 'http://localhost:47275/api/telemetry/trial/login'.",
"messageDetail": "No action was found on the controller 'LoginTelemetry' that matches the request."
}
If I change it to a [HttpGet] and put the appKey as a querystring, all is fine.
My app startup is very simple:
public void Configuration(IAppBuilder app)
{
log4net.Config.XmlConfigurator.Configure();
HttpConfiguration httpConfig = new HttpConfiguration();
httpConfig.MapHttpAttributeRoutes(); // <------ HERE
FilterConfig.RegisterHttpFilters(httpConfig.Filters);
LoggingConfig.RegisterHandlers(httpConfig.Services);
ConfigureOAuth(app);
ConfigureWebApi(httpConfig);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(httpConfig);
}
Can anyone spot why POST requests aren't being found? Thanks
If I take string parameter out and replace it with a request object, it works...
Instead of: public IHttpActionResult RecordLogin(string appKey)
I create a request model class:
public class PostLoginTelemetryRequest{
public string appKey {get;set;}
}
Then alter the signature:
public IHttpActionResult RecordLogin(PostLoginTelemetryRequest request)
Everything works fine (why it can't take a regular string like MVC5 web dev, I don't know, but anyway...)
(also note that I had tried this in every format from the client with the string method: form-url-encode, raw body, etc, so I'm fairly certain it wasn't a calling format issue).
I'm working with an ASP.NET Core RazorPage as an alternative to an MVC controller, and I want to be able to submit the client side form via XMLHttpRequest. I've already figured out the XSRF token bits so that passes the muster, but the RazorPages framework doesn't seem to process the inbound JSON payload and bind it to the property as expected.
Some code:
The page's model (.cshtml.cs):
public class IndexModel : PageModel
{
private Database database;
private ILogger logger;
[BindProperty]
public AddRequestModel MyRequest { get; set; }
public IndexModel(Database database, ILogger<IndexModel> logger)
{
this.database = database;
this.logger = logger;
}
public void OnGet() {}
public IActionResult OnPostValidate()
{
if (ModelState.IsValid)
{
// ...
}
return new BadRequestObjectResult(ModelState);
}
public async Task<IActionResult> OnPutConfirmAsync()
{
// ...
}
}
And the client side post:
const url = "?handler=validate";
const data = { MyRequest: this.fields };
await axios.post(url, data);
I have verified the data is being submitted correctly:
That X-XSRF-TOKEN header is being added by axios before the request is submitted. The fact that the server responds with a list of errors indicates that it's not the XSRF token causing the problem:
Note the MyRequest object does not contain the values from the request payload - it was not bound as expected (FirstName would not return a required error otherwise). How can I tell RazorPages to accept the JSON request and bind it to my property?
I was able to get the Binding works by adding FromBody similar to how it worked for ASP.NET Web API 2.
[BindProperty, FromBody]
public BroadcastMessageEditingViewModel BindingInfo { get; set; }
Use urlsearchparams with formdata.
In this post you can find more information How do I post form data with fetch api?
You would be better off posting your data to an API endpoint instead of a page controller. Create a class from ControllerBase and it will handle your JSON post correctly.