I have an action link:
#Html.ActionLink("Shopping cart", "Index", "Cart", new { returnUrl = Request.Url.PathAndQuery }, null)
and code that adds items to cart:
<script type="text/javascript">
$(document).ready(function () {
$("#addToCart_#(Model.ProductID)").click(function () {
var quantity = $("#Quantity_#(Model.ProductID)").val();
var productId = "#Model.ProductID";
var dataToBeSent = { 'quantity': quantity, 'productId': productId};
$.ajax({
type: "POST",
url: '/Cart/AddToCart/',
data: dataToBeSent,
success: function (result) {
$('#cartholder').html(result);
}
});
});
});
</script>
When I'm trying to follow action link after adding item to cart, Request.Url.PathAndQuery has value /Cart/AddToCart/.
How can I get current url?
You need to use:
Request.RawUrl
This will get the URL you see in the browser. When using Url writing as with MVC the Request.Url will be the rewritten path.
Looks to me like you are setting your URL to /Cart/AddToCart/. It's right there in your AJAX request: url: '/Cart/AddToCart/'. That's it -- that's your URL (not counting the scheme and host).
You're specifying type: "POST", so your payload (your data: dataToBeSent) isn't sent as part of the URL. The data only gets sent in the URL when you use GET. When you use POST, it's in the request body, not the URL.
(And don't just change it to a GET. It would seem to work for now, but would give you headaches later. GET requests can be cached by proxy servers -- not appropriate for requests that modify state, like adding things to a shopping cart.)
So in answer to the question you asked, Request.Url.PathAndQuery is how you get the URL. It's just that the URL is not what you want. You want to get your POST data, however that's normally done in ASP.NET MVC.
System.Web.HttpContext.Current.Request.Url
Related
It's my first time building a web api. I've successfully set up the model view controller and enabled token generation. However, I am stuck on how to pass the access token through the request header. After I have logged in and attempt to view another page, there is nothing in the header in regards to the authorization therefore I receive a 401 error. I've looked at several blogs, forums and articles over the past couple days and cannot come to a conclusion on how this is done. I have my jquery storing the header in a variable, but I am unsure on where that is stored and how to reference it or where to put the reference. I've messed around with setting it in global.asax and some of the config files, also at the top of the controller class. My next thought is to create a web page for each controller and storing the authorization there, even still I don't know how to dynamically place a token that would vary for other users. I feel like there is something very simple that I'm missing. I suppose my question is how do I store my javascript variable in each request header? Here is my javascript for reference:
$("#btnLogin").on('click', function () {
//var data = { Email: $("#loginEmail").val().trim(), Password: $("#textPwd").val().trim(), ConfirmPassword: $("#loginPwd").val().trim() };
$.ajax(
{
url: "/TOKEN",
type: "POST",
data: $.param({ grant_type: 'password', username: $("#loginEmail").val(), password: $("#loginPwd").val() }),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
success: function (resp) {
sessionStorage.setItem('userName', resp.userName);
sessionStorage.setItem('accessToken', resp.access_token);
var authHeaders = {};
authHeaders.Authorization = 'Bearer ' + resp.access_token;
$.ajax({
url: "https://localhost:44327/api/values",
type: "GET",
headers: authHeaders,
success: function (response) {
$("#loginEmail").val(),
$("#loginPwd").val(),
$("#msg").text(response)
}
});
},
error: function () {
$("#msg").text("Authentication failed");
}
})
});
I have a web application with a few cascading dropdown lists. So I use ajax to update the value of the next dropdown list. I put the javascript script in a separate file.
// Code that triggers when there is a change in Activity drop down.
$('#ActivityId').change(function () {
var activityId = $(this).val();
// Empty the Workstation.
$('#WorkstationId').empty();
$('.showhide-workstation').show();
var url = "~/WorkOrderSubmissions/GetWorkstationsByActivityJson";
// AJAX call that re-populate Workstation drop down depending on the Activity selected.
$.ajax({
type: 'POST',
url: url,
dataType: 'json',
data: { activityId: activityId },
success: function (codes) {
$('#WorkstationId').append('<option value=""></option>');
$.each(codes, function (i) {
$('#WorkstationId').append('<option value = "' + codes[i].Value + '">' + codes[i].Text + '</option>');
});
},
error: function (ex) {
$('#WorkstationId').append('<option value=""></option>');
}
}); // END $.ajax() on GetRejectCodesByActivityJson
}); // END $('#ActivityId').change()
The code works when I run it from inside Visual Studio. It does not work when I deploy it to my local web server. I deploy it to
http://localhost/mea
When I open Developer Tools in Chrome, I see the error.
POST http://localhost/~/WorkOrderSubmissions/GetLinesByWorkorderJson 404 (Not Found)
I tried to to change the url to
url = ~/WorkOrderSubmissions/GetLinesByWorkorderJson
url = /WorkOrderSubmissions/GetLinesByWorkorderJson
url = WorkOrderSubmissions/GetLinesByWorkorderJson
None of them work. I thought ~ is supposed to go to the root of the web application, which is http://localhost/mea.
The ~ syntax is only recognised by ASP.Net; it will be taken literally by any JS code. You need to provide the URL via your C# code to JS:
var url = '#Url.Content("~/WorkOrderSubmissions/GetWorkstationsByActivityJson")';
Or better yet:
var url = '#Url.Action("GetWorkstationsByActivityJson", "WorkOrderSubmissions")';
I'm using a Kendo grid to display results from a webservice. The webservice is accessed in a controller and then we point the Kendo grid dataSource to the controller like so:
JavaScript
var servicePath = "/Home/Search";
var postData = { "searchTerm" : searchTerm, "targetDB" : targetDB }
var grid = $("#grid1").kendoGrid({
pageable: {
pageSize: 10
},
dataSource: {
error: function (e) {
if (e.errors !== false) {
$("#errorContainer").html(e.errors);
}
},
transport: {
read: {
url: servicePath,
dataType: "json",
data: postData,
type: "POST"
}
},
},
dataBound: function (e) {
//Do Stuff
}
});
Controller
[HttpPost]
public ActionResult Search(string searchTerm, string targetDB)
{
//Do Search and Return JSON
}
Problem
This works wonderfully when my URL is http://localhost/Home/Index but fails whenever it's something else, such as http://localhost/ (default when project is run from root). I've experienced the same problems using a jQuery .ajax call as the kendo grid service call.
Question
So my question is, how can I put in the correct service URL for the Kendo Grid (or in general when pointing to a controller) and know it will work in all path variations?
I've tried using variations of location.host to get the full URL regardless then append the controller and method, but the Kendo service call fails with no error.
I imagine I should be able to parse the url and use what I need, but I've found that when I am at the root of the webpage I can't figure out what to put to make an ajax call work. I've tried using the controller/method and the entire url? I've also tried various techniques described below.
What am I missing? Is there a convention or technique I could use instead?
Edit
I also tried putting a hidden field on the page with a value of the controller URL:
<input type="hidden" value="#Url.Action("Search", "Home"); " id="serviceURL" />
And then using that value in the JS:
var servicePath = $("#serviceURL").val();
But I found that the value of #Url.Action() (Value : Home/Search) is the same whether your url is http://localhost/ or http:localhost/Home/Index, so no luck. This still does not work when you're on the root page where the url looks something like "localhost/".
Thanks!
I am making an ASP.net MVC application And I would like it so when a user clicks on a link it performs an ajax call sending data to the controller and then returning other data back to the view.
This is the method I would like to call in my controller:
public JsonResult GetImage(string url)
{
Image image = Image.FromFile(url, true);
byte[] byteImage = converter.ImageToBytes(image);
return Json(new { byteImage }, JsonRequestBehavior.AllowGet);
}
And here is the controllers location:
08983ClassLibrary\EpostASP\Controllers\CustomerController.cs
This is my Ajax Call:
$.ajax({
url: "~/Controllers/CustomerController/GetImage/",
type: 'POST',
contentType: 'application/json',
data: "url="+url,
success: function (image) {
document.getElementById("image").src = "data:image/png;base64," + image;
showImage();
}
});
When i place my breakpoints in the code I can see it hitting the ajax call then stepping over it never reaches the controller and doesnt give any errors.
Any ideas?
The main issue is here -
url: "~/Controllers/CustomerController/GetImage/",
You see, ~ is a server side literal, in other words, when you use this in a ASP.net server side path, it is replaced by the current server application folder location. This was the traditional ASP.Net way. This line has 2 errors -
This url will never work. Because its inside a string in JS and thus ASP.net does not know that it has to replace it with server path. Now comes the second error, even if ASP.net could detect and convert it, it will still not work. Because of the point I described at 2 -
Since you are using ASP.net MVC, it's not a good practice. The more conventional MVC way is to create routes and use those routes. Because in ASP.net you have the option to link to a page (.aspx, .ascx) directly. But MVC controller actions cannot be linked like that. So you have to create routes in your route config (check Global.asax) and then use that route as the url in here. BY default MVC apps will support the following format -
<host>/{controller}/action
example -
'localhost/Home/Index`
Notice that I didn't write HomeController, because by default controllers are supposed to ignore the trailing string Controller.
I hope this helped and just incase you are looking for a solution for your current situation try this (I haven't tested but it should be like this) -
$.ajax({
url: "Customer/GetImage",
type: 'POST',
contentType: 'application/json',
data: "url="+url,
success: function (image) {
document.getElementById("image").src = "data:image/png;base64," + image;
showImage();
}
});
but to be on the safe side, make sure you use -
[HttpPost]
public JsonResult GetImage(string url)
{
}
UPDATE:
the maproute (as requested in comment ) will work with any of these routes. But can also work with different routes config. Route config is very very flexible, it is just a matter to setup the routes the way it works for you. -
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute(
"...", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
routes.MapRoute(
"...", // Route name
"{controller}/{action}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
routes.MapRoute(
"...", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Customer", action = "GetImage", id = "" } // Parameter defaults
);
routes.MapRoute(
"...", // Route name
"Customer/GetImage/{id}", // URL with parameters
new { controller = "Customer", action = "GetImage", id = "" } // Parameter defaults
);
..... //all of these mentioned route will land on the same url
}
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
}
Your ajax script says it is looking for a POST action method.
$.ajax({type: 'POST',
Have you decorated the action method with POST?
[HttpPost]
public JsonResult GetImage(string url)
{
}
Also, adjust your ajax data parameter
$.ajax({
data: {
"url": url
},
If you are using chrome you can go the developer tools -> network tab and see all the server requests being made. Hit your button and you will see it pop up and show you the response codes, headers etc. In your case it will be red and will tell you what went wrong
If you are using web api... Your method is starting with "Get" GetImages so you need to decorate the method with [HttpPost]
I have found that using fiddler is the best way to see what is going on in MVC.
Start up fiddler, run the code again and see what actually came back. Most likely (as mentioned by Yorro) is that you got a 404 error and as you have no error handling in your json call, you wont ever see the error.
$.ajax({
url: '#Url.Action("GetImage", "Customer")',
type: 'POST',
contentType: "application/json; charset=utf-8",
data: "url="+url,
success: function (image) {
document.getElementById("image").src = "data:image/png;base64," + image;
showImage();
}
});
If using IE, and your controller is hitting the first time only add ...
$.ajax({
cache:false,
...
Some time it will work or some time not work so don't mention URL such as static "~/Controllers/CustomerController/GetImage/" please follow the dynamic way
So you will change the code snippet such as below
$.ajax({
url: "#Url.Action("GetImage", "CustomerController")",
type: 'POST',
contentType: 'application/json',
data: "url="+url,
success: function (image) {
document.getElementById("image").src = "data:image/png;base64," + image;
showImage();
}
});
hopefully this code will be resolved your problem !!
I have this Kendo UI dropdownlist with a select event that is handled by a JavaScript function.
I need to call an action result from a controller that runs a LINQ query to populate a Kendo UI grid on my page. My problem is the only way I can find to handle this even is with JavaScript and I have been unable to figure out how to call my action result from my controller from the JavaScript event function.
This is what the DropDownList looks like...
#(Html.Kendo().DropDownList()
.Name("Options")
.DataTextField("Text")
.DataValueField("Value")
.BindTo(new List<SelectListItem>() {
new SelectListItem() {
Text = "Policies Not Archived",
Value = "1"
},
new SelectListItem() {
Text = "View All Policies",
Value = "2"
},
new SelectListItem() {
Text = "Filter Policies",
Value = "3"
}
})
.Events(e =>
{
e.Select("select");
})
)
and my JavaScript event handler that needs to call the action result
function select(e) {
}
and depending on the selection an ActionResult like this,
public ActionResult ViewAllPolicies()
{
//mycode
}
see this post
var url = '#Url.Action("ViewAllPolicies","YourController")';
$.ajax({ url: url, success: DataRetrieved, type: 'POST', dataType: 'json' });
in controller
public ActionResult ViewAllPolicies()
{
//Should return json format
}
url – this is the URL where request is sent. In my case there is
controller called contacts and it has action calles
ListPartiesByNameStart(). This action method takes parameter
nameStart (first letter of person or company). success – this is the
JavaScript function that handles retrieved data. You can write there
also anonymous function but I suggest you to use functions with names
because otherwise your code may get messy when functions grow. type –
this is the type of request. It is either GET or POST. I suggest you
to use POST because GET requests in JSON format are forbidden by
ASP.NET MVC by default (I will show you later how to turn on GET
requests to JSON returning actions). dataType – this is the data
format that is expected to be returned by server. If you don’t assign
it to value then returned result is handled as string. If you set it
to json then jQuery constructs you JavaScript object tree that
corresponds to JSON retrieved from server.
Instead of returning json, you can also return a PartialView and in the .done function grab an element and replace it with the results from the partial view. PartialView actions basically return a fragment of HTML, and so you can just stuff that anywhere you want on the page:
$.ajax({
url: urlToPartialViewAction,
type: 'POST',
dataType: 'JSON',
data: '123'
})
.done(function (result) {
$('#someDivPlaceholder').replaceWith(result);
});
You could have something like a link or grey div and wire up to it's click event and then call this, the link might say "View Receipt" and when you click it you call an action that returns a partial view with the receipt, and so when they click it the div/link is replaced with the result. Kind of like the "View More Comments" links you see on social sites.
Note that you can't have a partial view by itself, it must be called through an action
public PartialViewResult _GetReceipt(string id)
{
ReceiptViewModel vm = //query for receipt data
return PartialView(vm);//render partial view and return html fragment
}
Once the select function executes, you need to make an AJAX call back to your Controller. You can use jQuery.ajax() (a wrapper for the most common AJAX operations) in the select function,
function select(e) {
var url = '#Url.Action("ViewAllPolicies", "PolicyController")';
var selectedPolicy = $('#Options').val(); // The option selected
$.ajax({
url: url,
type: 'POST',
dataType: 'JSON',
data: selectedPolicy
})
.done(function (data) {
// Display the data back from you Controller
});
}
You can look at the Kendo site for more info on how the DropDownList works.