Can't figure out how WEB API Calls URLS - javascript

I'm learning WEB API on ASP.NET web forms and already implementing it on my project to show some data on a modal but I can't figure out how is the api url created.
I followed this tutorial
https://learn.microsoft.com/en-us/aspnet/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api
this is my AJAX call
<script type="text/javascript">
function ShowUserModal(lnk, IdColaborador) {
debugger
//var s = lnk.id;
//var start = s.indexOf("lnkEdit");
//var end = s.lastIndexOf("_");
//sub = s.substring(start, end);
//s = s.replace(sub, "IdMatriz");
//var hidden = document.getElementById(s);
//var id = hidden.value;
//alert(id);
var uri = 'api/users/';
$.ajax({
URL: uri,
type: 'POST',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
data: IdColaborador,
success: function (data) {
alert("Saved successfully");
},
fail: function(jqXHR, textStatus) {
alert("Request failed: " + textStatus);
}
})
}
</script>
this is my controller
public class UsersController : ApiController
{
public User user { get; set; }
//public IEnumerable<User> GetAllUsers()
//{
// return users;
//}
public IHttpActionResult GetUser(int id)
{
user = new User();
string constr = ConfigurationManager.ConnectionStrings["ControloInterno_ConnectionString"].ConnectionString;
using (SqlConnection con = new SqlConnection(constr))
{
using (SqlCommand cmd = new SqlCommand("spOperadores", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Action", "SELECTINF");
cmd.Parameters.AddWithValue("#IdColaborador", id);
con.Open();
using(SqlDataReader sdr = cmd.ExecuteReader())
{
while (sdr.Read())
{
user.Nome = sdr["Nome"].ToString();
user.Criador = sdr["criador"].ToString();
user.DataAdm = Convert.ToDateTime(sdr["dataadmin"]);
user.AltData = Convert.ToDateTime(sdr["AltData"]);
user.Telemovel = sdr["tele"].ToString();
user.Departamento = sdr["Departamento"].ToString();
user.status = sdr["status"].ToString();
user.DescricaoPerfil = sdr["DescricaoPerfil"].ToString();
user.Observacoes = sdr["Observacoes"].ToString();
}
}
}
}
return Ok(user);
}
}
and I had to use this in global.asax to work
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = System.Web.Http.RouteParameter.Optional }
);
}
so my question is, how is the url generated? why is it called api/users if my controller is called UsersController and the class is called User

If you are using attribute routing make sure you call the following function on your HttpConfiguration:
// Web API routes
config.MapHttpAttributeRoutes();
You can read more about attribute routing here:
Web api attribute routing
Or if you will use MVC instead read here:
Attribute routing in MVC

Related

When I send Objects of Javascript to my Spring boot application, it says "Invalid character found in the request target"

I have searched for every possibility for this problem but couldn't figure out why is it happening.
It want to save an object in localstorage in javascript, then fetch this object and send data to my spring boot application. But when i call ajax, it gives me an error which is below
java.lang.IllegalArgumentException: Invalid character found in the request target [/product/cart/items?{%22cartItems%22:[{%22itemId%22:%22asfasfa%22,%22itemCount%22:2},{%22itemId%22:%22ijhar%22,%22itemCount%22:3}]}]. The valid characters are defined in RFC 7230 and RFC 3986
at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:491) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:260) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590) [tomcat-embed-core-9.0.36.jar:9.0.36]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.36.jar:9.0.36]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_265]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_265]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.36.jar:9.0.36]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_265]
JavaScript code
$(document).ready(function() {
function getAllItemsFromCart() {
let product;
product = JSON.parse(localStorage.getItem("items"));
return product;
}
let itemsList = {};
let cartItems = [];
let items = {};
items['itemId'] = 'asfasfa';
items['itemCount'] = 2;
cartItems.push(items);
items = {};
items['itemId'] = 'ijhar';
items['itemCount'] = 3;
cartItems.push(items);
itemsList['cartItems'] = cartItems;
localStorage.setItem('items', JSON.stringify(itemsList));
let itemsList1 = getAllItemsFromCart();
$.ajax({
url: "[[#{/product/cart/items}]]",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: "GET",
data: JSON.stringify(itemsList1),
dataType: "json",
success: function(response, status, xhr) {
console.log("This is success message")
},
error: function(response) {
console.debug(response.status + ":" + response.statusText);
},
beforeSend: function() {
//talman.showAjaxLoader();
},
complete: function() {
//talman.closeAjaxLoader();
}
});
});
Java controller
#GetMapping(value = "/cart/items",consumes = "application/json", produces = "application/json")
#ResponseBody
public String addProductToCart(#RequestBody CartItemsBean itemList){
return "sucess";
}
Bean
class ItemsBean {
private String itemId;
private String itemCount;
public String getItemId() {
return itemId;
}
public void setItemId(String itemId) {
this.itemId = itemId;
}
public String getItemCount() {
return itemCount;
}
public void setItemCount(String itemCount) {
this.itemCount = itemCount;
}
}
public class CartItemsBean {
private List<ItemsBean> cartItems;
public List<ItemsBean> getCartItems() {
return cartItems;
}
public void setCartItems(List<ItemsBean> cartItems) {
this.cartItems = cartItems;
}
}
For security reasons, Spring Boot doesn't accept some special characters on QueryParams.
But I think in your case you need to use JSON.stringfy to wrap it.
By the way, It is a bit weird to have a GET receiving body or acting as a POST or PATCH.

Why does my controller action add 2 new records instead of one

I have a simple razor view with a button that is supposed to add a new record to a table in my SQL DB.
The button has attached an ajax function that calls the controller.
I tried two different controllers; both controllers work but add 2 new records instead of one. See below code snippets:
Button click event in razor view
$('#addLike')
.click(function (e) {
var proposalId = 12;
var url = "#Url.Action("AddLike", "Proposal")/?proposalId=" + proposalId;
$.ajax({
type: "POST",
url: url,
dataType: "json",
traditional: true,
success: function(response) {
window.location.href = actions.common.proposals;
}
});
});
Class model
public class Proposal_Likes
{
public int? Proposal_Id { get; set; }
public int Id { get; set; } (... Identity, DatabaseGenerated)
}
Controller
public ActionResult AddLike(int proposalId)
{
var proposal_Like = new Proposal_Likes
{
Proposal_Id = proposalId
};
UnitOfWork.InsertOrUpdate(proposal_Like);
UnitOfWork.Commit();
return Json("Success");
}
alternative Controller
public ActionResult AddLike(int proposalId)
{
using (SqlConnection con = new SqlConnection(cs))
{
using (SqlCommand cmd = new SqlCommand("addProposalLike", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#propsalId", SqlDbType.Int).Value = proposalId;
con.Open();
cmd.ExecuteNonQuery();
}
}
return Json("Success");
}
I have been working on this for almost 2 days, debugged through the entire code but can't find the cause or a clue where to dig deeper. When I execute the SQL stored procedure manually inside SSMS it does add only one record.
Any help will be appreciated!
Additional info:
No submits, no other buttons on the view
I found the cause:
With my ajax function I was using a parameter in the url.Action in order to pass it to an ActionResult controller:
$.ajax({
type: "POST"
var url = "#Url.Action("AddLike", "Proposal")/?proposalId=" + proposalId;
...
public ActionResult AddLike(int proposalId)
{ ...}
This caused the controller to be called twice.(Why ... I don't know).
When I pass the parameter via the data part of the ajax call
var url = "#Url.Action("AddLike", "Proposal")";
$.ajax({
type: "POST",
url: url,
dataType: "json",
data: {
proposalId: 24,
},
into a model and the controller
public class ProposalViewModel
{
public int proposalId { get; set; }
}
public ActionResult AddLike(ProposalViewModel model)
{ var propId = model.proposalId
...
}
the controller is called only once as expected.

Why some C# api method need [HttpPost] while some don't need it?

I have two methods are in the same controller file to receive data from JavaScript ajax.
First C# api controller code is
public class News
{
public int ID { get; set; }
public string Title { get; set; }
public string Intro { get; set; }
public string Story { get; set; }
public string Images { get; set; }
public DateTime DateModified { get; set; }
public DateTime DateCreated { get; set; }
}
public void InsertData([FromBody]News newsinfo)
{
conn.ConnectionString = mdc.ConnectonString;
cmd.Connection = conn;
if (newsinfo.ID > 0)
{
cmd.CommandText = "UPDATE [News] SET [Title] = N'" + newsinfo.Title + "', [Intro] = N'" + newsinfo.Intro + "', [Story] = N'" + newsinfo.Story + "', [Images] = N'" + newsinfo.Images + "', [DateModified] = #DateModified WHERE [ID] = " + newsinfo.ID;
cmd.Parameters.AddWithValue("#DateModified", DateTime.Now);
}
else
{
cmd.CommandText = "INSERT INTO [News] ([Title], [Intro], [Story], [Images], [DateCreated], [DateModified]) VALUES (N'" + newsinfo.Title + "', N'" + newsinfo.Intro + "', N'" + newsinfo.Story + "', '" + newsinfo.Images + "', #DateCreated, #DateModified)";
cmd.Parameters.AddWithValue("#DateCreated", DateTime.Now);
cmd.Parameters.AddWithValue("#DateModified", DateTime.Now);
}
conn.Open();
int send = cmd.ExecuteNonQuery();
conn.Close();
}
Above code will receive data from this JavaScript
function InsertData() {
var newsData = {
ID: editingID,
Title: $("#txbTitle").val().replace(/[\"]/gm, "\"").replace(/[\']/gm, "''"),
Intro: $("#txbIntro").val().replace(/[\"]/gm, "\"").replace(/[\']/gm, "''"),
Story: $(".ql-editor").html().replace(/[\"]/gm, "\"").replace(/[\']/gm, "''").replace(/http.\/\/[a-z:0-9]+/gm, "").replace(/\/Images.Temp\//gm, "/Images/News/"),
Images: imagesToUpload.replace(/Temp/gm, "News")
$.ajax({
url: "api/Database/InsertData",
method: "POST",
data: newsData,
success: function (result, status, xhr) {
if (imagesToUpload != "") {
var fileslist = {
filenames: ""
}
fileslist.filenames = imagesToUpload;
console.log(fileslist);
$.ajax({
url: "api/FileUpload/StoreImages",
method: "POST",
data: fileslist,
success: function (result, status, xhr) {
ViewState();
},
error: function (xhr, status, error) {
alert(error);
}
});
}
else if (imagesToUpload == "") {
ViewState();
}
},
error: function (xhr, status, error) {
alert(error);
}
});
}
The second C# api controller code is
public class NewsId
{
public int[] id { get; set; }
}
[HttpPost]
public void DeleteData([FromBody]NewsId newsId)
{
conn.ConnectionString = mdc.ConnectonString;
cmd.Connection = conn;
if (newsId.id.Length > 0)
{
foreach (int id in newsId.id)
{
cmd.CommandText = "SELECT [Images] FROM [News] WHERE [Id] = " + id;
conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
string images = "";
while (reader.Read())
{
images = reader[0].ToString();
}
conn.Close();
string[] files = Regex.Split(images, ";");
foreach (string file in files)
{
if (file != "")
{
string path = HttpContext.Current.Server.MapPath("~") + Regex.Replace(file, "/Images", "Images");
File.Delete(path); // /Images/Temp/
}
}
cmd.CommandText = "DELETE FROM [News] WHERE [Id] = " + id;
conn.Open();
int d = cmd.ExecuteNonQuery();
conn.Close();
}
}
}
And it's receive data from this JavaScript
function DeletingNews(news_id) {
var newsId = {
id: news_id // news_id is Array
}
$.ajax({
url: "api/Database/DeleteData",
method: "POST",
data: newsId,
success: function (result, status, xhr) {
ViewState();
},
error: function (xhr, status, error) {
alert(error);
}
});
}
I don't understand why the First code doesn't needs to have the [HttpPost] while the Second code needs it otherwise the Ajax will return
405 method not allowed
Both are running fine now but I just don't understand why some's needs [HttpPost] while another's doesn't need it?
By default API Controller provides with get,put,post and delete
By Default Get All is let say IEnumerable GetAll()
By Default Get is string Get(int id)
By Default Post is void Post([FromBody]object value )
By Default Put is void Put(int id,[FromBody]object value )
By Default delete is void Delete(int id)
closely take a look at the signature used and the return types
based on these the action take place.
so now if you want to add a new action lets say Post then you need to decorate it with HttpPost attribute for controller to understand which action to call
Finally, I solve this problem by just reading on Routing in ASP.NET Web API article.
Because my C# API method name is begin with "Delete" that match on Http verb rules.
public void DeleteData([FromBody]NewsId newsId)
{
conn.ConnectionString = mdc.ConnectonString;
cmd.Connection = conn;
if (newsId.id.Length > 0)
I just have to change my Ajax method from "POST" to "DELETE" like the code below then this issue will be solved.
function DeletingNews(news_id) {
console.log(news_id);
var newsId = {
id: news_id
}
$.ajax({
url: "api/Database/DeleteData",
method: "DELETE", // <-- Changed from "POST"
data: newsId,
success: function (result, status, xhr) {
ViewState();
},
error: function (xhr, status, error) {
alert(error);
}
});
}
Or, another solution is change the C# method name from "Delete" to something else and keep the Ajax method with "POST" like the codes below.
public void RemoveData([FromBody]NewsId newsId) // <-- Change method's name from "DeleteData" to "RemoveData"
{
conn.ConnectionString = mdc.ConnectonString;
cmd.Connection = conn;
if (newsId.id.Length > 0)
function DeletingNews(news_id) {
console.log(news_id);
var newsId = {
id: news_id
}
$.ajax({
url: "api/Database/RemoveData", // <-- Change action url from "DeleteData" to "RemoveData"
method: "POST",
data: newsId,
success: function (result, status, xhr) {
ViewState();
},
error: function (xhr, status, error) {
alert(error);
}
});
}

i have an error while export excel file using c# mvc

i am using asp.net mvc webapi and ajax in my project
i am calling controller using ajax and sending data with ajax
here is my ajax code
var bobj = {};
bobj.data = data;
CallAjax('post',common,'attendancesheetdownload',bobj,_getholidaylist.onsuccestendancesheetdownload, '');
function CallAjax(method, baseUrl, strUrl, strData, onSuccess, onFailure) {
callDebugger();
var dataValue = null;
var ContentType = "application/json; charset=utf-8";
strUrl = baseUrl + strUrl;
method = method.toUpperCase();
if (method == "GET") {
dataValue = strData;
}
else if (method == "POST") {
dataValue = JSON.stringify(strData);
}
callLoader(true);
$.ajax({
type: method,
url: strUrl,//users/signin
contentType: ContentType,
dataType: 'json',
data: dataValue,
async: false,
success: onSuccess,
error: function (err) {
callLoader(false);
swal({
title:err, text: "", type: "error",
showCancelButton: false, closeOnConfirm: true, confirmButtonText: "OK",
}, function (isConfirm) {
window.location = "signin";
});
//console.log(err);
}
});
}
and here is my c# controller code for excel generate
[HttpPost]
[Route("attendancesheetdownload")]
public JsonResult AttendanceSheetDownload(List<AttendanceModel> data)
{
//List<AttendanceModel> holidaylist = new List<AttendanceModel>();
try
{
System.Data.DataTable dt = new System.Data.DataTable();
using (XLWorkbook wb = new XLWorkbook())
{
//DataTable dt = new DataTable();
dt.Columns.Add("Employee Name");
dt.Columns.Add("Leaves");
// dt.Columns.Add("URL");
foreach (var item in data)
{
var row = dt.NewRow();
row["Employee Name"] = item.user_id;
row["Leaves"] = Convert.ToString(item.days);
// row["URL"] = item.URL;
dt.Rows.Add(row);
}
// dt = attendacemodel;
wb.Worksheets.Add(dt, "CusDetail");
wb.ShowRowColHeaders = false;
wb.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
wb.Style.Font.Bold = true;
Response.Clear();
Response.Buffer = true;
Response.Charset = "";
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment;filename=Customers.xlsx");
using (MemoryStream MyMemoryStream = new MemoryStream())
{
wb.SaveAs(MyMemoryStream);
MyMemoryStream.WriteTo(Response.OutputStream);
Response.Flush();
Response.End();
}
}
return Json(data);
}
catch (Exception ex)
{
throw ex;
}
finally
{
data = null;
}
}
i dont see any error at c# side it easly pass all the step but the file is not downloading
and
when its comes to onsuccess method of ajax its give me object object error
can some one guide me how to download excel file with ajax c# and webapi

How to upload object from JavaScript to Rest API

I have a Rest API:
[HttpPost]
[Route("Services/Image/Upload")]
public string Upload([FromBody]GalleryItem galleryItem)
{
try
{
var appSettings = ConfigurationManager.AppSettings["GalleryPath"].ToString();
using (FileStream fs = new FileStream(appSettings + galleryItem.KeyCode + ".jpg", FileMode.Create))
{
using (BinaryWriter bw = new BinaryWriter(fs))
{
byte[] data = Convert.FromBase64String(galleryItem.Base64);
bw.Write(data);
bw.Close();
}
}
return "OK";
}
catch (Exception ex)
{
return ex.ToString();
}
}
and I call it from my Javascript client like:
var galleryItem = new Object();
galleryItem.Base64 = base64;
galleryItem.KeyCode = '1234';
url = "http://my domain name/api/Services/Image/Upload";
$.ajax({
type: 'POST',
url: url,
data: JSON.stringify(galleryItem),
contentType: 'application/json; charset=utf-8',
dataType: 'text/plain',
success: function (msg) {
alert('Image saved successfully !');
},
error: function (jqXHR, textStatus, err) {
$('#error').html('Error: ' + err);
}
});
my model:
public class GalleryItem
{
public string Base64 { get; set; }
public string KeyCode { get; set; }
}
I a testing this via a mobile device as I am taking image from camera to send up.
Nothing appears to happen? I just 'Error: error'?
thanks
ADDITIONAL:
After porting to a test script (wished I had done that sooner) I found the error is this:
net::ERR_NAME_NOT_RESOLVED
Though why I am unsure as I am calling another method from that api with no issues
Solved!
Thank God!
I changed the url to relative:
url = "/api/Services/Image/Upload";
without prefixing with domain name.
it must have got confused and thought it needed cors? (guess here)

Categories

Resources