Hi im learning about REST API and used this link http://www.codeproject.com/Articles/588909/ASP-NET-WEB-API-Basics-MVC-4 . And i have developed a small API . Following is my controller
public class FileController : ApiController
{
[HttpGet]
public List<files> get()
{
DBQuery k = new DBQuery();
List<files> listOfFiles = k.GetAll();
return listOfFiles;
}
[HttpPost]
public int get(int v)
{
return (v);
}
having two methods namely get and upload and by using the below url i can access the get method
http://localhost:53081/api/File
but when i give http://localhost:53081/api/File/1 this i can access upload method . Still im getting the get methods result
what went wrong in my code . Kindly help me . im new to this
update
if i cal the method upload im still getting the get methods result on my screen
what went wrong
Images
and for this http://localhost:53081/api/File/1 also im getting 404 error and i have used REST Client plugin to post the url
You might be best to rename your methods like so
[HttpGet]
public List<File> Get()
{
return myFileClass.MyMethodThatReturnsAListOfFiles;
}
[HttpGet]
public File Get(int id)
{
return myFileClass.MyMethodThatReturnsASpecificFile(id);
}
The upload method you have is a bit confusing as it should really take in a File object and be restricted to only use the HttpPost method. Youd need to use a rest client (plugin for chrome, or use Fiddler) to get this to work, but stick with the pattern above and you'll be ok.
My guess at a method to replace your upload method is
[HttpPost]
public File Post(File uploadedFile)
{
return myFileClass.MyMethodThatSavesAFileAndReturnsItWithANewId(uploadedFile);
}
Related
i'm working with an API that i didn't made and there's no documentation about it, i have this class and method
[Route("api/[controller]")]
[ApiController]
public class SearchController : ControllerBase
{
[Route("[action]")]
[HttpGet]
public async Task<int> someMethod([FromQuery] QueryObject query)
{
//some logic
}
and this is my query object
public QueryObject
{
public int id {get; set;}
}
but i can't get to the breakpoint in the controller, i'm not quite sure how the url is suppose to be
Make a get request to: {the API's base url}/api/Search/{method name}
if u chose the mvc api project so it works with actions methods.
For example ...api/[controllername]/action_method
Other things are just classic C#
My bad, i'm kind of new to API, i haven't used before the Route("[action]")
so the correct url was localhost:0000/api/search/someMethod?id=1
I am new to ASP.Net WebAPI and I'm trying to use the NorthWind database to practice.
Now, I have a ProductsController which contains a GetAllProducts and a GetAllProductsById actions.
On the client-side, I have a multiselect dropdown control which is been populated with the categories of products from the CategoriesController class.
I want to populate a second dropdown control (not a multiselect) with the Products from the Categories that was selected in the category dropdown list.
My GetAllProductsById controller looks like this:
public IHttpActionResult GetAllProductsById([FromUri]int[] id)
{
using (var ctx = new NorthwindEntities())
{
<some codes...>
}
return Ok(productList);
}
Calling this service from the client, the URL look like this: http://localhost:1234/api/Products/GetAllProductsById?id=1&id=2&id=3
This is looks good with few parameters but what if the User selects more categories (let's say 30 out of 40 categories)? This means the URL would be so long.
So, I decide to use a POST to do a GET's job by decorating my action with HttpPost:
[HttpPost]
public IHttpActionResult GetAllProductsById([FromBody]int[] id)
This allows me to send the id parameters from the Body of my request.
Now, I am wondering if this style is correct or if someone can point me to a much cleaner way of passing a long list of parameters from a client to my webservice.
Thanks in advance.
NB:
Using Elasticsearch is not an option at the as suggested in the link below:
HTTP GET with request body
I tried using a modal class but it also has the same effect
http://localhost:1234/api/Products/GetAllProductsById?input.id=1&input.id=2
You could do something a bit hacky: use HTTP headers.
First the client should add the ID list as a header to its HTTP request (C# example follows):
var webRequest = System.Net.WebRequest.Create(your_api_url);
webRequest.Headers.Add("X-Hidden-List", serialized_list_of_ids);
And then on the API side:
[HttpGet]
public IHttpActionResult GetAllProductsById()
{
string headerValue = Request.Headers.GetValues("X-Hidden-List").FirstOrDefault();
if (!string.IsNullOrEmpty(headerValue))
{
var results = DeserializeListAndFetch(headerValue);
return Ok(results);
}
else
{
var results = ReturnEverything();
return Ok(results);
// or if you don't want to return everything:
// return BadRequest("Oops!");
}
}
DeserializeListAndFetch(...) and ReturnEverything() would do the actual database querying.
You can have the array of Id in a model class and in the method parameters just accept type of that class. Like
Modal Class
Public class modal
{
Public int[] Ids {get;set;}
}
Your Contoller
public IHttpActionResult GetAllProductsById([FromBody] modal m)
{
//Some logic with m.Ids
}
Your JSON if you are using any UI to consume this API
{"Ids" :[1,2,3,4,5,6]}
Hope this Helps,
I have an AngularJS app sending an object array to a Web API controller method through a POST request. On the server I have the following method definition:
[HttpPost]
[Route("Active")]
public async Task<IHttpActionResult> Post(IList<Media> mediaFiles)
{
try
{
foreach (var file in mediaFiles)
{
await Task.Factory.StartNew(() => PublicData.SetInactiveMedia(file.Id, file.Active));
}
return Ok();
}
catch (ArgumentException e)
{
return BadRequest(e.Message);
}
}
I use the $resource factory in order to interact with the server (but I have to mention that I have also tried with $http and no difference showed up). This is the method:
var activeMedia = $resource('/api/adminhotspotsmedia/active', { save: { method: 'POST' } });
var setActiveMedia = function (mediaFiles) {
activeMedia.save(mediaFiles);
}
The mediaFiles variable is an array of objects that absolutely match the Media model on the server.
In the Developer's Console I can see this Request Payload associated with the request:
So the array is trying to get to the server, but it cannot. The server gets a null value for the list of objects. I will add that I have tried using:
[FromBody] tag
dynamic instead of IList<Media>
IList<object> instead of IList<Media>
The problem persists. What could it be?
By default the model binder wont know what to do with the interface unless you have a custom model binder that knows what to expect and what the desired behavior is.
Alternatively you can use an actual List<Media>
[HttpPost]
[Route("Active")]
public async Task<IHttpActionResult> Post(List<Media> mediaFiles) { ... }
or array Media[]
[HttpPost]
[Route("Active")]
public async Task<IHttpActionResult> Post(Media[] mediaFiles) { ... }
I'm new to ASP.NET MVC and I'm confused about how in a compiled language like C#, class names can have any meaning after the project has been built. Can someone explain to me how the building process takes
public class SomePageController : Controller {
public ActionResult Index() { return View(); }
}
and grabs the names SomePage and Index to create a URL map SomePage/Index that calls the function Index()? I only understand how this works if there is some other C# file that somehow able to look at all classes derived from the Controller class and get a string that is their name without the suffix "Controller". But that seems weird to me coming from a C++ background because I've never seen a way that a language can have of variables referencing their own name, nor have I ever seen a way to iterate through all classes derived from a certain class.
Maybe someone can show me how to write a C# procedure like
public class SomePageController : Controller {
public ActionResult Index() { return View(); }
}
public class SomeOtherPageController : Controller {
public ActionResult Index() { return View(); }
}
public void printPageNames ( void )
{
// ... Will print "SomePage, SomeOtherPage" to the console
}
What you need to read into is Reflection. It allows you to look at all of the classes, properties, etc within an assembly.
To directly answer your question, Jon Skeet has the starting point of how to accomplish this.
Your code would look something like this:
var assembly = Assembly.GetExecutingAssembly();
foreach (var controller in assembly.GetTypes().Where(a => a.Name.EndsWith("Controller"))
{
Console.WriteLine(controller.Name.TrimEnd("Controller"));
}
I have simple console application, which send json data to controller.
Client.PostAsJsonAsync("http://[site].azurewebsites.net/api/Decision", report);
And controller:
public class DecisionController : ApiController
{
private readonly TaskManager _taskManager = new TaskManager();
[HttpGet]
public Decision Get(int id)
{
return _taskManager.GetDecision(id);
}
[HttpPost]
public void Post(Decision decision)
{
_taskManager.UpdateDecision(decision);
}
}
Visual Studio debugger shows, that a request does not reach the controller (not trigger a breakpoint). Console application does not throw any exceptions, and report variable does not equal to null.
How can I debug this?
You might want to take a look at Fiddler which is a free tool to debug web requests. Basically, it monitors all web requests going through your machine and lets you see what they look like. You can also generate new ones straight from there too. That way, you can at least make sure that your request is properly formatted.
Also, I noticed that you are trying to call your controller directly when you should be calling an action on your controller instead. When you request GET api/Decision, you also need to provide an action method. I do not know enough of your model to restructure your controller properly, but here is an example based on a simple user profile.
public class ProfileController : ApiController
{
[HttpGet]
public string FullName()
{
return "Foo Bar";
}
[HttpPost]
public void FullName(string newName)
{
// ...
}
[HttpGet]
public int Age()
{
return 22;
}
[HttpPost]
public void Age(int newAge)
{
// ...
}
}
As you can see, the HttpVERB attribute is not used to dispatch requests to a controller to specific methods. It is used to distinguish the different overloads of related restful actions. In this case, it is used to distinguish between getting and setting a FullName and an Age property.
If you with to keep your controller intact, you should be requesting:
POST http://[site].azurewebsites.net/api/Decision/post
GET http://[site].azurewebsites.net/api/Decision/get