I'm trying to get some info I sent by form to angularJS in my c# asp.net backend, and I'm having trouble doing it.
Visual Studio won't let me compile because it says:
Error CS0120: an object reference is required for the nonstatic field, method, or property 'member'
That's is my controller
public class SearchController : ApiController
{
public string Get()
{
string test = HttpContext.Request.QueryString["txt_search"];
return test;
}
}
Here's what I got in my angularjs:
$scope.sendForm = function () {
console.log($scope.model.search);
$http({
method: 'GET',
url: '/api/search?txt_search=' + $scope.model.search
})
.then(function () {
console.log('sucesso a executar o post');
}, function () {
console.log('Erro ao executar o post');
});
};
As suggested in the comments, you should just be able to change your method definition and skip this altogether:
public string Get(string txt_search)
{
return txt_search;
}
Alternatively, to reference the current request, I believe you need to use the following (note the addition of .Current):
string test = HttpContext.Current.Request.QueryString["txt_search"];
The reason is that HttpContext defines Request as an instance property. The only public static property is Current, which returns an instance of HttpContext through which you can reach Request.
Welcome to Stack Overflow,
Your Angular code is correct
You need to pass a parameter on server side to collect txt_search value
Here it is:
[HttpGet]
[Route("/api/search")]
public string mySearchMethod(string txt_search)
{
//something here with txt_search
return "OK";
}
Both of the above solution will work, but for another approach as you are using asp.net web api and router you can make it as below as well
In your Angular code, simple pass the search as below
```
$scope.sendForm = function () {
console.log($scope.model.search);
$http({
method: 'GET',
url: '/api/search/'+ $scope.model.search
})
.then(function () {
console.log('sucesso a executar o post');
}, function () {
console.log('Erro ao executar o post');
});
};
```
Notice
url: '/api/search/'+ $scope.model.search
and change the Action method as below
```
[HttpGet]
[Route("/api/search/{txt_search}")]
public string mySearchMethod(string txt_search)
{
//something here with txt_search
return "OK";
}
```
by doing this you don't have to worry about the name of the parameter txt_search
whatever you mention in route [Route("/api/search/{txt_search}")], you will get the value in same parameter.
Related
This is the pattern of the object I'm getting when I printed out my list value from rest controller.
[
{
"name": "Jon",
"isUser": true
},
{
"name": "Ween",
"isUser": false
}
]
but the problem is I dont know how can I get this value to my ajax call. I need that values for further work. But whenever I'm calling this controller my ajax return error 500.
this is my rest controller:
#RequestMapping(value = "/getusers", method = RequestMethod.GET)
public List userShow(HttpServletRequest request, Model model) {
List userlist = new ArrayList();
try{
userlist = JSONArray.fromObject(userService.getUserList());
System.out.println(userlist);
}catch (Exception e){
logger.error(e);
}
return userlist;
}
I can clearly see the list of the printed userList from system.out but i'm not sure why these values are not going in the ajax call. Maybe I've to change the return of my function , I've given list as I want my data as the provided data I have given in the first part of the question.
and
my ajax call :
$.ajax({
type: "GET",
url: "/getusers",
success: function (response) {
console.log(response);
if(response === true) {
user = true;
}
else{
user = false;
errorShow = "error getting values";
}
},
async: false
});
when this url hits, values are seen in the controller but in the console.log i see
GET http://localhost:3000/getusers 500
error. How can I get those values in the response section?
I think you are using #Controller annotation at the class level.
If you use #RestController you will not have to write #Responsebody explicitly.
Also instead of
#RequestMapping(value = "/getusers", method = RequestMethod.GET)
you can use new method annotations like so.
#GetMapping("/getusers")
Just use #Responsebody annotation on method level and you don't have to convert list to array anymore. Return the list directly.
Change
JSONArray.fromObject(userService.getUserList())
To
userService.getUserList()
If you really want to return the List you can use ResponseEntity like this:
#RequestMapping(value = "/getusers", method = RequestMethod.GET)
public ResponseEntity <List> userShow(HttpServletRequest request, Model model) {
List userlist = new ArrayList();
try {
userlist = userService.getUserList();
System.out.println(a);
} catch (Exception e) {
logger.error(e);
}
URI uri = ServletUriComponentsBuilder.fromCurrentRequest().path("/").buildAndExpand("").toUri();
return ResponseEntity.created(uri).body(userlist);
}
Notice that I got rid of the JSONArray.fromObject() because ResposneEntity will take of converting the List into JSON for you.
Also it's preferred to specify the List type, for example: List<User>
I'm trying to post strings from an AngularJS application (using $http) to a server built on ASP.NET WebApi, but I get 404 as soon as I add a parameter.
The client code is this
$scope.add = function () {
// ...cut...
$http({ method: "POST", url: url, data: { fileString: "test string" }}).then(
function successCallback(response) {
$log.info(response.data);
}
);
}
The server code is
[HttpPost]
public IHttpActionResult UploadExcel(string fileString) {
// cut
}
I get a 404, but if I remove the parameter on server side it works, so i can use a server side code like this
[HttpPost]
public IHttpActionResult UploadExcel() {
// cut
}
What is wrong? Should I pass the data in a different way? I tried different combination but I can't get it work.
What you want to do is send a string, not a JSON object as you are doing right now with { fileString: "test string" }. When I want to send a string, what I normally do is that I send data from Angular like this:
$http.post("/Search/QuickSearch?searchQuery="+ searchString);
And my controller I make ready to receive a string like this:
[HttpPost]
public IHttpActionResult QuickSearch(string searchQuery)
{
// cut
}
If I want to send a JSON object, I tell my controller what it should expect, like this:
[HttpPost]
public IHttpActionResult SaveActivity(ActivityEditForm form);
{
// cut
}
public class ActivityEditForm
{
public int? Id { get; set; }
[Required]
public string Title { get; set; }
public string Description { get; set; }
}
And then send my JSON from Angular like this:
$http.post("/Activity/SaveActivity", { form: activity });
I suggest you should capture the request send by Angular. By default, Angular send parameters in a json string in request body.
I'm not sure wether Asp.net can parse them from json string in body.
So, you can try to add the below codes (also need jQuery)
angular.module('yourApp').config(function ($httpProvider) {
$httpProvider.defaults.transformRequest = function(data){
if (data === undefined) {
return data;
}
return $.param(data);
}
});
The first error is in the controller, [FromBody] should be used with the input parameter.
public IHttpActionResult UploadExcel([FromBody]string fileString)
Then the data variable on the client should be a single string, so
$http({ method: "POST", url: url, data: "test string" }).then(
Anyway I found some issue with this solution later, it seems the simplest but I suggest to avoid it.
Best solution
Thank to #Squazz answer and this SO answer I strongly suggest a change in the webapi controller, client was correct. Just introduce a class to handle a single string and adapt the input parameter
// new class with a single string
public class InputData {
public string fileString { get; set; }
}
// new controller
[HttpPost]
public IHttpActionResult UploadExcel([FromBody] InputData myInput) {
string fileString = myInput.fileString;
// cut
}
This way JSON code from the client is automatically parsed and it's easy to change the data input.
Extra tip
$scope.add angular function was correct as in the question, but here is a more complete example
$scope.testDelete = function () {
var url = "http://localhost/yourAppLink/yourControllerName/UploadExcel";
var data = ({ fileString: "yourStringHere" });
$http({ method: "POST", url: url, data: data }).then(
function successCallback(response) {
console.log("done, here is the answer: ", response.data);
}, function errorCallback(response) {
console.log("an error occurred");
}
);
}
I'm making an ASP.NET Web API web service, and an HTML/javascript page to test it. The issue I'm having is with passing a complex data parameter and having it come through properly in the web API controller.
I know there are numerous similar questions and I've read them and tried the solutions and haven't solved it. I have also read some JQuery documentation.
Here's my controller:
public class TitleEstimateController : ApiController
{
public IHttpActionResult GetTitleEstimate([FromUri] EstimateQuery query)
{
// All the values in "query" are null or zero
// Do some stuff with query if there were anything to do
}
}
public class EstimateQuery
{
// Various fields
}
The route mapping in WebApiConfig.cs:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{query}"
);
And the javascript:
var uri = 'api/titleEstimate/';
var query = {
"username": $("#user").val(),
// other fields
};
$.getJSON(uri,query)
.done(function (data) {
$('#product').text("OK");
})
.fail(function (jqXHR, textStatus, err) {
$('#product').text('Error: ' + err);
});
Currently I'm getting a 404. I tried $.getJSON(uri + '/' + query) but that didn't work either. Before I was passing this object I was calling it successfully so I think the routing is generally OK. I tried a type converter, but that didn't help, still a 404. Does anyone see what I'm missing/doing wrong?
Answer
You are using the wrong uri. You need api/titleEstimate/getTitleEstimate. That explains and will resolve your 404.
Answer to Follow Up Question
Everything else you're doing almost works. After you resolve the 404, you'll find that you aren't receiving the value FromUri, and you'll have a follow up question. So, you need to change your route config to this:
config.Routes.MapHttpRoute(
name: "Default",
routeTemplate: "api/{controller}/{action}"
);
Then you'll not only resolve your 404 but also receive the FromUri value that you're sending as query string parameters.
Demo
Here is a fiddle for evidence, which is calling into this controller, which is hosted LIVE here. The only thing I changed in the working version are the uri to resolve the 404 and the route config to make sure you receive the FromUri value. That's all.
HTML
<label>Username:
<input id="user" />
</label>
<button id="submit">Submit</button>
<button id="submit-fail">Submit Fail</button>
<div id="product"></div>
JavaScript
This will succeed.
Note, we only need domain because we doing cross-site scripting here for the demo purpose.
var domain = "https://cors-webapi.azurewebsites.net";
$("#submit").click(function () {
var uri = domain + '/api/titleEstimate/getTitleEstimate';
var query = {
"username": $("#user").val(),
// other fields
};
$.getJSON(uri, query)
.done(function (data) {
$('#product').text(data);
})
.fail(function (jqXHR, textStatus, err) {
$('#product').text('Error: ' + err);
});
});
This will 404.
$("#submit-fail").click(function () {
var uri = domain + '/api/titleEstimate';
var query = {
"username": $("#user").val(),
// other fields
};
$.getJSON(uri, query)
.done(function (data) {
$('#product').text(data);
})
.fail(function (jqXHR, textStatus, err) {
$('#product').text('Error: ' + err);
});
});
Controller
public class TitleEstimateController : ApiController
{
public class EstimateQuery
{
public string username { get; set; }
}
public IHttpActionResult GetTitleEstimate([FromUri] EstimateQuery query)
{
// All the values in "query" are null or zero
// Do some stuff with query if there were anything to do
if(query != null && query.username != null)
{
return Ok(query.username);
}
else
{
return Ok("Add a username!");
}
}
}
You can read more details about WebApi routing here. From reading it you can probably come up with an alternative solution within your route config. There are also lots of terrific examples in this blog post.
First, I would try to use the attribute routing feature of web.api like this:
[RoutePrefix("api/titleestimate")]
public class TitleEstimateController : ApiController
{
[HttpGet]
public IHttpActionResult GetTitleEstimate([FromUri] EstimateQuery query)
{
// All the values in "query" are null or zero
// Do some stuff with query if there were anything to do
}
}
It would also be helpful to see the request in your dev tools. I disagree with Colin that you should make this a POST, because HTTP POST is supposed to be used to create new items. You are trying to get information so HTTP GET makes sense.
I think Web.Api assumes methods are GETs by default, but declarating it with the HttpGet attribute will for sure take care of that.
For complex objects, I usually send them in the message body rather than the URL.
Would you have any objection to an approach similar to the answer of this question?
How to pass json POST data to Web API method as object
It seems like the more straightforward/natural approach.
Something like (untested, but should be close):
[RoutePrefix("api/titleestimate")]
public class TitleEstimateController : ApiController
{
[HttpGet]
public IHttpActionResult GetTitleEstimate([FromBody] EstimateQuery query)
{
// All the values in "query" are null or zero
// Do some stuff with query if there were anything to do
}
}
public class EstimateQuery
{
public string QueryName{ get; set; }
public string Whatever{ get; set; }
}
$(function () {
var query = {QueryName:"My Query",Whatever:"Blah"};
$.ajax({
type: "GET",
data :JSON.stringify(query),
url: "api/titleEstimate",
contentType: "application/json"
})
.done(function (data) {
$('#product').text("OK");
})
.fail(function (jqXHR, textStatus, err) {
$('#product').text('Error: ' + err);
});
});
I'm a very new comer to the asp.net web api world. I've got the basic understanding of get(), put(), post() and delete.
In my application, I require two more get() method. An explanation is given below-
public class StudentController : ApiController
{
public IEnumerable Get()
{
//returns all students.
}
//I would like to add this method=======================
[HttpGet]
public IEnumerable GetClassSpecificStudents(string classId)
{
//want to return all students from an specific class.
}
//I also would like to add this method=======================
[HttpGet]
public IEnumerable GetSectionSpecificStudents(string sectionId)
{
//want to return all students from an specific section.
}
public Student Get(string id)
{
//returns specific student.
}
}
There is already a $http.get(..) in angularjs controller.
My question is, how can I call the two additional get() methods from angular controller.
Well, I haven't used asp.net mvc in forever. But you be able to do something like:
public class StudentController : ApiController
{
[Route("students")]
public IEnumerable Get()
{
//returns all students.
}
//I would like to add this method=======================
[HttpGet]
[Route("students/class/{classId}")]
public IEnumerable GetClassSpecificStudents(string classId)
{
//want to return all students from an specific class.
}
//I also would like to add this method=======================
[HttpGet]
[Route("students/section/{sectionId}")]
public IEnumerable GetSectionSpecificStudents(string sectionId)
{
//want to return all students from an specific section.
}
[Route("students/{id}")]
public Student Get(string id)
{
//returns specific student.
}
}
You could also specify routes in the routeconfig like this:
routes.MapRoute(
name: "students",
url: "students/class/{classId}",
defaults: new { controller = "Student", action = "GetClassSpecificStudents", id = UrlParameter.Optional }
);
You have to try for your self. And you can read more about it here and here.
Not that you have your specified routes you can add angular $http.gets for each route.
var url = "whateverdoma.in/students/"
$http.get(url)
.success()
.error()
var url = "whateverdoma.in/students/class/" + classId;
$http.get(url)
.success()
.error()
var url = "whateverdoma.in/students/filter/" + filterId;
$http.get(url)
.success()
.error()
What you want to do is write costum angular resource method, to call your API.
Use angular $resource and not $http - > it is the more common usage (and more REST oriented: $resource wraps $http for use in RESTful web API scenarios).
Read about it
Find how to add a resource to the $resource service.
Here is an example:
.factory('Store', function ($resource, hostUrl) {
var url = hostUrl + '/api/v3/store/';
return $resource("", { storeId: '#storeId' }, {
getSpecific: {
method: 'GET',
url: hostUrl + '/api/v3/store-specific/:storeId'
}
});
})
I have a post request I am doing like so:
var addProject = function (project, id) {
return $.ajax(projectUrl, {
type: "POST",
data: { project: project, id: id }
});
};
This is all fine, and it send up my project object (in JSON) with no problem. What i want to do is this request but also add in a key (that does not belong in the project object) that I can pass to the server controller. Any idea if I can do this, or what is a good way to do this. I really don't want to have to go back and change my object models to account for a key that I will only need every once in awhile.
This is an ASP.NET MVC4 project, and it is going back to a web api controller if that matters.
EDIT: here is my server side stuff
public HttpResponseMessage PostNew(Project project, int id)
{
//TODO grab the client to add the project to
Uow.Projects.Add(project);
Uow.Commit();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, project);
//response.Headers.Location = new Uri(Url.Link("ApiControllerAction", new { id = client.ID }));
return response;
}
Maybe I am not being clear enough. I want to pass in the project object, and then just an int variable. Passing project alone works, but if I try to pass the int it gives me a 400 error
var addProject = function (project) {
return
$.ajax(projectUrl, {
type: "POST",
data: {data1 : 'Object',data2: 'variable'}
});
};
You have just to send 2 data params., object and var..
Easiest way to pass a complex object is to JSON-encode it:
var addProject = function (project) {
return $.ajax(projectUrl, {
type: "POST",
contentType: 'application/json',
data: JSON.stringify(project)
});
};
To decode this on the server side, you will need a JSON decoder of some kind. I'm sure C# has some available.