asp.net core 2 web api routing - asp.net-core-webapi

I am using asp.net core 2 web API, I had created three methods first and third works fine but when I hit the second method it routed me to the first method did I write correct route or something is wrong with routes?
[Route("api/[controller]")]
public class HospitalController : Controller
{
[HttpGet]
public IActionResult Get()
{
return new ObjectResult("");
}
[HttpGet("searchstring:aplha")]
public IActionResult Get(string searchstring)
{
return new ObjectResult(searchstring);
}
[HttpGet("{Id:int}")]
public IActionResult Get(int Id)
{
return new ObjectResult(Id);
}
}

Below is your corrected code:
[Route("api/[controller]")]
public class HospitalController : Controller
{
[HttpGet]
public IActionResult Get()
{
return new ObjectResult("");
}
[HttpGet("{searchstring}")]
public IActionResult Get(string searchstring)
{
return new ObjectResult(searchstring);
}
[HttpGet("{Id:int}")]
public IActionResult Get(int Id)
{
return new ObjectResult(Id);
}
}
It will work properly for all the three methods, if you call URL like "/api/Hospital/1" for int values, "/api/Hospital/abc" for string values.

Related

Asp.net Core Web Api Multiple Controller Method For Get All

I have a controller which gets data from a database but i want to have multiple methods [Actions] for the same GetAll Method based on different key.
Example
consider this DB
can i have a controller with different GetAll method based on CountryID, AddressID, DepartmentID like this
[ApiController]
[Route("api/Users")]
public class UsersController : ControllerBase
{
//Without a key
[HttpGet]
public IEnumerable<User> GetAll()
{
return repository.GetAll();
}
[HttpGet("{addressId}")]
public async IEnumerable<User> GetAll([FromRoute]string addressId)
{
User user= repository.GetAll(addressId);
}
[HttpGet("{CountryID}")]
public async IEnumerable<User> GetAll([FromRoute]string CountryID)
{
User user= repository.GetAll(CountryID);
}
[HttpGet("{DepartmentID }")]
public async IEnumerable<User> GetAll([FromRoute]string DepartmentID )
{
User user= repository.GetAll(DepartmentID );
}
}
and if i can how can i call this different method from the http request.
thanks in advance
You can define routing rules like below:
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
// Without a key
[HttpGet]
// GET /api/Users
public IEnumerable<User> Get()
{
return repository.GetAll();
}
[HttpGet("AddressId/{id}")]
// GET /api/Users/AddressId/123
public IEnumerable<User> GetByAddressIdAll([FromRoute] int id)
{
....
}
[HttpGet("CountryId/{id:int}")]
// GET /api/Users/CountryId/456
public IEnumerable<User> GetByCountryIdAll([FromRoute] int id)
{
....
}
[HttpGet("DepartmentID/{id:int}")]
// GET /api/Users/DepartmentId/678
public IEnumerable<User> GetByDepartmentIdAll([FromRoute] int id)
{
....
}
}
See the documentation: Attribute routing with Http verb attributes

Upload a file to one drive using graph api from the asp.net webform

I want to Upload files to onedrive using graph api from the asp.net webform.
public class ValuesController1 : ApiController
{
AuthenticationProvider[] AuthenticationProviders = new AuthenticationProvider[]
{
new AuthenticationProvider {}
};
// GET api/<controller>
public IEnumerable<AuthenticationProvider> GetAllAuthInfo()
{
return AuthenticationProviders;
}
// GET api/<controller>/5
[HttpGet]
public string Get(int id)
{
return "value";
}
// POST api/<controller>
[HttpPost]
public void Post([FromBody] string value)
{
}
// PUT api/<controller>/5
[HttpPut]
public void Put(int id, [FromBody] string value)
{
}
// DELETE api/<controller>/5
[HttpDelete]
public void Delete(int id)
{
}
}
here is ApiController.
AuthenticationProvider is a model class.
I following this DOC(https://learn.microsoft.com/en-us/onedrive/developer/rest-api/getting-started/graph-oauth?view=odsp-graph-online)
but, I don't know How to do with [step 1.Step 1. Get an authorization code]
Let me know with an example.
thanks.

Error 405 not allowed on HttpPost in Asp.net core 3.1 web api

When i try to post the raw text with postman the server answer 405 not allowed. I try to add
app.UseCors(options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
services.AddCors();
without any solution.
Whis is the code of the application:
[Route("api/[controller]")]
[ApiController]
public class VideoWallController : ControllerBase
{
// GET: api/<ValuesController>
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/<ValuesController>/5
[HttpGet("{id}")]
public string Get(int id)
{
return "value";
}
// POST api/<ValuesController>
[HttpPost]
public string prova([FromBody] VideoCallBack test)
{
return "true;";
}
[HttpPost]
public void teststring(string test)
{
}
// PUT api/<ValuesController>/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
}
// DELETE api/<ValuesController>/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
If you want to reach that endpoint using the /teststring suffix, you need to put that in the endpoint template:
[HttpPost("teststring")]
public void teststring(string test)
{
}
Or, as #maghazade said, you can just reach the endpoint using the controller URL, without a suffix: https://localhost:44336/api/videowall
Also, the CORS settings are not needed to access the API using Postman. CORS is used only to configure the API access through a web application running on a web browser.
Firstly,as maghazade said,there are two endpoints for the post method.You can try to use [HttpPost("teststring")] as ferhrosa said.You can also add [action] to [Route("api/[controller]")],so that routes of actions will include their action names.If you add other actions with post method,the routes will not conflict anymore.
[Route("api/[controller]/[action]")]
[ApiController]
public class VideoWallController : ControllerBase
{
// GET: api/<ValuesController>/Get
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/<ValuesController>/Get/5
[HttpGet("{id}")]
public string Get(int id)
{
return "value";
}
// POST api/<ValuesController>/prova
[HttpPost]
public string prova()
{
return "true;";
}
// POST api/<ValuesController>/teststring
[HttpPost]
public void teststring([FromBody]string test)
{
}
// PUT api/<ValuesController>/Put/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
}
// DELETE api/<ValuesController>/Delete/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
And if you want to pass string test from Body,you need to add [FromBody] and select JSON in postman.
result:

Unable to load Swagger API documentation with ODATA controller

We are trying to generate the swagger UI with OData and NSwag but we are ended up with lot of issues.
We are using OData controllers instead of ControllerBase
Startup file configuration
services.AddOData(); services.AddSwaggerDocument();
Startup Configure method
app.UseMvc(builder =>
{
builder.Select().Filter().Expand().MaxTop(1000).Count();
builder.MapODataServiceRoute("ODataRoutes", "api/v1", GetEdmModel(app.ApplicationServices));
builder.EnableDependencyInjection();
});
app.UseSwagger();
app.UseSwaggerUi3();
we are using values controller inheriting ODataController
[Route("api/[controller]")]
[ApiController]
public class ValuesController : Microsoft.AspNet.OData.ODataController
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
// GET api/values/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return "value";
}
// POST api/values
[HttpPost]
public void Post([FromBody] string value)
{
}
// PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
}
// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
We getting error like " /swagger/{documentName}/swagger.json"
Are we missing something ?

How do I pass data between controllers and overloaded actions?

I have one controller that takes a username and pass and checks against a database. IF the user is authenticated, I want to call an overloaded action on another controller.
My end goal is to authenticate a user against an old table from a MySQL db (I have this part working). Once the user is authenticated, I would like to be able to "automagically" forward the person to the built in MVC registration page but I would like to populate some fields in the view using data obtained from the first controller (the old databse info).
When I try something like what I have below I get an error about the Register() methods being ambiguous. I've also tried using the [ActionName("Register2")] attribute but then the error returned says it cant find a method named Register2.
public class MigrateAccountController : Controller
{
OldUserRepository oldDb = new OldUserRepository();
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(User u)
{
if (oldDb.isValid(u.username, u.password))
return RedirectToAction("Register", "Account", u);
return View(u);
}
}
public class AccountController : Controller
{
public IFormsAuthenticationService FormsService { get; set; }
public IMembershipService MembershipService { get; set; }
protected override void Initialize(RequestContext requestContext)
{
if (FormsService == null) { FormsService = new FormsAuthenticationService(); }
if (MembershipService == null) { MembershipService = new AccountMembershipService(); }
base.Initialize(requestContext);
}
public ActionResult Register(User u)
{
return View(u);
}
public ActionResult Register()
{
ViewBag.PasswordLength = MembershipService.MinPasswordLength;
return View();
}
}
First thing you cannot have the same action name on the same controller that is accessible on the same verb. You need to either change the action name or use a different HTTP verb:
public class AccountController : Controller
{
public IFormsAuthenticationService FormsService { get; set; }
public IMembershipService MembershipService { get; set; }
protected override void Initialize(RequestContext requestContext)
{
if (FormsService == null) { FormsService = new FormsAuthenticationService(); }
if (MembershipService == null) { MembershipService = new AccountMembershipService(); }
base.Initialize(requestContext);
}
[HttpPost]
public ActionResult Register(User u)
{
return View(u);
}
public ActionResult Register()
{
ViewBag.PasswordLength = MembershipService.MinPasswordLength;
return View();
}
}
and in order to pass data between actions, well, if you are using GET, you could pass them as query string parameters when redirecting.
Or IMHO a better way would be not to redirect in this case but simply return the corresponding view by passing it the proper view model:
[HttpPost]
public ActionResult Index(User u)
{
if (oldDb.isValid(u.username, u.password))
{
return View("~/Account/Register.aspx", u);
}
return View(u);
}
You can use the TempData values in this case.

Resources