I have FriendlyUrls nuget package added to WebForm application.
In RegisterRoutes I have:
var settings = new FriendlyUrlSettings();
//settings.AutoRedirectMode = RedirectMode.Off;
settings.AutoRedirectMode = RedirectMode.Permanent;
routes.EnableFriendlyUrls(settings);
I created 2 pages WebForm1.aspx and WebForm2.aspx
On WebForm1.aspx I referenced jQuery v1.9.1 in the head simply added the following inside the default div tag in the body:
<div id="dvResult"></div>
<script type="text/javascript">
$(function() {
$.fpm("GetCategories", '', function (res) {
$("div#dvResult").html(res.d);
}, function (xhr, ajaxOptions, thrownError) {
$("div#dvResult").html("<b>" + thrownError + "</b><br/>Status: " + xhr.status + "<br/>" + xhr.responseText);
});
});
$.fpm = function fpm(methodName, arguments, onSuccess, onError) {
var proto = (("https:" == document.location.protocol) ? "https://" : "http://");
var hostname = window.location.hostname;
if (window.location.port != 80)
hostname = window.location.hostname + ":" + window.location.port;
var loc = proto + "" + hostname + "/WebForm2.aspx";
$.ajax({
type: "POST",
url: loc + "/" + methodName,
data: "{" + arguments + "}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: onSuccess,
error: onError
});
};
</script>
WebForm2.aspx is kept stock standard after adding the file to the project, except for 1 method added to the code behind:
[System.Web.Services.WebMethod(EnableSession = false)]
public static string GetCategories()
{
return "hi";
}
When I run the page WebForm1.aspx I get the following result:
{"Message":"Authentication failed.","StackTrace":null,"ExceptionType":"System.InvalidOperationException"}
When view the request in fiddler I can see the friendly url did not strip the .aspx extension (which is a good thing):
http://localhost:14918/WebForm2.aspx/GetCategories
However as shown above, the FriendlyUrlSettings has the AutoRedirectMode set to RedirectMode.Permanent and when you uncomment the line for RedirectMode.Off and comment the Permanent out, then you actually get the result "Hi" printed on the screen.
Anyone has any ideas what the cause could be or how to add an exclusion to the routes?
I have tried to following but it does not seem to affect in any way the 401 result I keep getting:
//routes.Add(new Route("*Remote.aspx*", new StopRoutingHandler()));
//routes.Ignore("{remote}", new { remote = #".*\Remote.aspx(/.)?" });
You just saved my day.Below is the c# version of the code.In case of the master pages just paste PageMethods.set_path("default.aspx") before closing Content tag
public static void RegisterRoutes(RouteCollection routes)
{
var settings = new FriendlyUrlSettings();
settings.AutoRedirectMode = RedirectMode.Permanent;
routes.EnableFriendlyUrls(settings, new CustomFriendlyUrlResolver());
}
public class CustomFriendlyUrlResolver : WebFormsFriendlyUrlResolver
{
public override string ConvertToFriendlyUrl(string path)
{
if (HttpContext.Current.Request.PathInfo != "")
{
return path;
}
else
{
return base.ConvertToFriendlyUrl(path);
}
}
}
This is late but in case someone has same issue. Simple fix, set RedirectMode.Off instead of RedirectMode.Permanent. For the Ajax part do the following for the url key:
$.ajax({
type: "POST",
url:'<%=ResolveUrl("sample.aspx/methodname")%>'
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (msg) {
alert("Worked");
},
failure: function (msg) {
alert("Failed");
}
});
I had similar issue, the above solution worked for me. This is a quick fix but I wouldn't recommend it for production. This error occurs partly because of the FriendlyUrl vs non FriendlyUrl redirect method settings hence the server is receiving requests from an unauthenticated user. For production, make sure to put in place necessary security details and accept request from authenticated users otherwise the exposed methods from code behind can cause a huge security risk.
Faced with stripping vast amounts of PageMethods from a large established application, I found the following alternative solution to switching over to WebApi (turning AutoRedirectMode off still allows my file extensions to be displayed when requested directly and I really don't want that).
Instead use a custom FriendlyUrls.Resolver in your App_Start/RouteConfig file. The only change to existing pages was to add the following markup to each page using PageMethods:
<script>PageMethods.set_path("/Pages/Subjects.aspx")</script>
Here is the sample code in VB:
Imports Microsoft.AspNet.FriendlyUrls
Imports Microsoft.AspNet.FriendlyUrls.Resolvers
Public Module RouteConfig
Sub RegisterRoutes(ByVal routes As RouteCollection)
routes.EnableFriendlyUrls(New FriendlyUrlSettings() With {.AutoRedirectMode = RedirectMode.Permanent}, New IFriendlyUrlResolver() {New CustomFriendlyUrlResolver()})
End Sub
End Module
Public Class CustomFriendlyUrlResolver
Inherits WebFormsFriendlyUrlResolver
Public Overrides Function ConvertToFriendlyUrl(path As String) As String
If HttpContext.Current.Request.PathInfo <> "" Then Return path Else Return MyBase.ConvertToFriendlyUrl(path)
End Function
End Class
Hope that helps someone!
Ended up creating WebApi project and after a few new problems arriving (CORS related), got it working and actually feel that it's probably a better solution than pagemethods.
Related
I am sending a complex string (which is a combination of the style attribute, ID and label text) from the script using $.ajax() . I went through a couple of questions on similar problems. But maybe I am not able to understand where am I getting it wrong.
This is the script I am using :
$(".btnSaveStyle").click(function (e) {
var comp1Style = "";
var comp2Style = "";
$(".box").children(".comp1").each(function () {
var style = $(this).attr('style');
var title = $(this).text();
var componentClass = $(this).attr('class');
comp1Style = comp1Style + style + "#" + componentClass + "#" + title + "$";
});
alert(comp1Style); //I get the style here
$.ajax({
type: "POST",
async: true,
url: 'AjaxRecieveStyle.aspx/GetStyle',
data: comp1Style
});
And in the C# I am accessing it in the following way :
[WebMethod]
protected void GetStyle(string style)
{
var recievedStyle = style;
Customer customer = (Customer)Session["existing_user"];
if (customer != null)
{
EventComponent eventComponent = new EventComponent();
string txtComp1 = recievedStyle;
string[] separateComponents = txtComp1.Split('$');
string[] individualComponent = new string[5];
foreach (string position in separateComponents)
{
individualComponent = position.Split('#');
if (individualComponent[0].Equals(""))
{
//do nothing
}
else
{
eventComponent.EventID = 1;
eventComponent.Image = "";
eventComponent.Style = individualComponent[0].ToString();
eventComponent.ComponentType = individualComponent[1].ToString();
eventComponent.Title = individualComponent[2].ToString();
int id = new EventComponentLogic().Insert(eventComponent);
}
}
}
}
Now :
1) : Should I use a JSON object to pass the data ?
OR
2) : Please show me what am i doing wrong in here ?
1) Yes it's better to send data using JSON - I mean, it'd be much easier to understand what's happening when anyone will look at that code in a year from now. And it's also much easier to extend the protocol based on JSON.
2) I suggest you to add logging at the very beginning of the GetStyle(string style) method. Then please try to get to it by explicitly typing the URL in your browser (or better using PostMan - see below for a link, PostMan will help you with testing POST requests as I see you have a POST request there) and ensure that the web-server code works.
And only if it works then please try your front-end AJAX request.
I suppose that you don't handle POST request correctly in your WebAPI. It will only handle GET requests. Please look at this SO question for details: Simple post to Web Api
3) Link to PostMan: https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en
Did some digging and came up with this link: http://www.aspsnippets.com/Articles/Calling-ASPNet-WebMethod-using-jQuery-AJAX.aspx
The source code from the website shows that you may be missing some key features in your ajax call:
function ShowCurrentTime() {
$.ajax({
type: "POST",
url: "Default.aspx/GetCurrentTime",
data: '{name: "' + $("#<%=txtUserName.ClientID%>")[0].value + '" }',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: OnSuccess,
failure: function(response) {
alert(response.d);
}
});
}
While this is (obviously) intended for their example you see that they set the following attributes that you do not
contentType: "application/json; charset=utf-8",
dataType: "json",
success: OnSuccess,
failure: function(response) {
alert(response.d);
}
While the success and failure attributes are definitely optional I believe that setting your content type and datatype would really help you out here.
I changed my script to the following :
$.ajax({
type: "POST",
async: true,
url: 'AjaxRecieveStyle.aspx',
data: { style: comp1Style } //as I want to pass the parameter 'style' which is internally a JSON array.
});
I fetched the variable style in my C# in the following way (without using [WebServices]) :
I wrote a method GetStyle(string style) to get the data being sent from the ajax call.
Note: I did not call AjaxRecieveStyle/GetStyle from my script as the method is not accessible in my C# method . The data is actually received from the Page_Load method.
I access the variable sent from the script using Request.Params["style"].
My C# method is :
protected void Page_Load(object sender, EventArgs e)
{
GetStyle(Request.Params["style"]);
}
protected void GetStyle(string style)
{
var recievedStyle = style;
//do something on the recieved data!
}
This wil be an alternative to anyone who don't want to send JSON data actually !But sending data using JSON format will increase the readability of the code..
Need some advice - doing a project with MVC 4 - used to Forms and Ajax.
Normally I do AJAX calls
My code looks like this :
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "#SiteConfig.BaseUrl/assessment/getquestion",
data: "{'AssessmentId':" + "'" + AssessmentId + "'" + ",'PageNumber':" + PageIndex + "}",
dataType: "json",
beforeSend: function(){
$('#ajaxLoader').show();
$('#questionContainer').hide();
},
success: function (msg) {
var data = msg.d;
},
complete: function(){
$('#ajaxLoader').hide();
$('#questionContainer').show();
},
error:function (request, status, error){
alert(request.responseText);
alert(request);
$('#ajaxLoader').hide();
//window.location = '#SiteConfig.BaseUrl/questionnaire';
}
});
[HttpPost]
public JsonResult GetQuestion(Guid AssessmentId, Int32 PageNumber)
{
... my code
return this.Json(assessmentInfo, JsonRequestBehavior.AllowGet);
}
I keep getting HTML that is returned instead of JSON - it basically just sends me the HTML for the entire page back in the method - what am I doing wrong?
Debugging the problem yields the following result from javascript:
Javascript : SyntaxError: JSON.parse: enexpected character
Furthermore, if I add a breakpoint to the C# GetQuestion method, it is not being hit.
Could this be a URL routing issue?
Also, for the guys that are commenting on Naming conventions : the purpose of this method is to get a question. Naming conventions should follow business logic first, then technical conventions. Calling the method postquestion implies that I am posting a question which doesnt make sense at all.
You should edit your GetQuestion method like this:
[HttpPost]
public JsonResult GetQuestion(Guid AssessmentId, Int32 PageNumber)
{
//my code
return this.Json(myClass,JsonRequestBehavior.AllowGet);
}
Please also get your naming conventions right, if you get something, call the method GET. If you post someting call the method POST.
Ok, I found the problem.
It was indeed a routing problem that caused the issue.
Here is a funny situation that I'm in.
I'm developing an ASP.Net web site using VS 2008 and .Net Framework 3.5, and I want to use jquery ajax in a test page, the code looks like this:
C# Method
[WebMethod]
public static string test()
{
return "Server Response" ;
}
$(document).ready(function() {
$("#myDiv").click(function() {
$.ajax({
type: "POST",
url: "AjaxTest.aspx/test",
data: "",
contentType: "application/json;charset=utf-8",
dataType: "json",
success: function(msg) {
// Replace the div's content with the page
// method's return.
alert(msg.d);
},
error: function(result){
alert("error occured. Status:" + result.status
+ ' --Status Text:' + result.statusText
+ " --Error Result:" + result);
}
});
});
});
So When I use Jquery 1.4.4 like this :
I get : Status 200; Status Text: OK
When I use Jquery 1.5 I get: Status 200; Status Text: Parsererror
So I created a new WebSite in Visual Studio, copy and pased the code there, and it works fine !!!! I can't figure out what causes the problem.
Also I have used methods with parameter, and setting data:"{}", and removing data completely, but nothing seems to work.
I don't know if has to do anything with the DevExpress components that I'm using or not.
I also found a good answer which was working with complete method like this :
complete: function(xhr, status) {
if (status === 'error' || !xhr.responseText) {
alert("Error");
}
else {
var data = xhr.responseText;
alert(data);
//...
}
}
But I don't know if it will work fine or there might be some other problem with this method too. I also don't know how to access response data from here.
But my main concern is finding out what is causing the problem in my website.
UPDATE: Well today in Google Chrome console I noticed some syntax problems with JQuery 1.5
they are as below:
Uncaught SyntaxError: Unexpected token <
jQuery.jQuery.extend.globalEvaljquery.js:593
jQuery.ajaxSetup.converters.text scriptjquery.js:7175
ajaxConvertjquery.js:7074
donejquery.js:6622
jQuery.ajaxTransport.send.callbackjquery.js:7441
The issue isn't so easily solved with fiddler, although it's a great tool.
The issue I think is described here, and for now use the complete event.
there are some issues that will be resolved in jQuery 1.5.1
See:
jQuery returning "parsererror" for ajax request
as it was posted there,
complete: function (xhr, status) {
if (status == 'error' || !xhr.responseText) {
handleError();
}
else {
var data = xhr.responseText;
//...
}
}
Although the interesting thing is - this works for me with jsonp data when I query amazon's service (code amazon was based on some other posting on the net I don't have the ref too) ala:
//resp is simple a placeholder for autocomplete's response which I will need to call on a global scope.
var resp;
var filter;
$(document).ready(function () {
//http://completion.amazon.com/search/complete?method=completion&q=halo&search-alias=videogames&mkt=1&x=updateISSCompletion&noCacheIE=1295031912518
filter = $("#productFilter").autocomplete({
source: function (request, response) {
resp = response;
$.ajax({
url: "http://completion.amazon.com/search/complete",
type: "GET",
cache: false,
dataType: "jsonp",
success: function (data) {
//data[1] contains an array of the elements returned from the service.
//use .map to enumerate through them.
response($.map(data[1], function (item) {
//debugger;
return { label: item, value: item, id: item}
}))
},
data: {
q: request.term,
"search-alias": "videogames",
mkt: "1",
callback: '?'
}
});
},
minLength: 2,
select: function (event, ui) {
//$('#browseNode option:first').attr('selected', 'selected');
alert('selected');
},
open: function () {
$(this).removeClass("ui-corner-all").addClass("ui-corner-top");
},
close: function () {
$(this).removeClass("ui-corner-top").addClass("ui-corner-all");
}
});
});
//this is the method that will be called by the jsonp request
function updateISSCompletion() {
alert('updateiss');
resp(completion[1]);
}
You should use Fiddler - the great web debugging proxy. With its help you can watch for all communication between server and client
Not sure if this will help, but the ajax() API specifies that they have changed the return object for the success() callback function. This is from the jQuery API
As of jQuery 1.5, the success callback function receives a "jqXHR" object (in jQuery 1.4, it received the XMLHttpRequest object). However, since JSONP and cross-domain GET requests do not use XHR, in those cases the jqXHR and textStatus parameters passed to the success callback are undefined.
You can find it here if it helps at all...
jQuery $ajax API
I am running into a similar problem, and am unable to pull the JSON object from any callback functions.
I had this problem too but in PHP When i put in 'remote.php':
`echo $msg`'
problem occurs. When I use json_encode():
echo json_encode($msg);
then everything works.
This is strange, because I get response from server with status 'OK', so then function 'success' should work not 'error'. In 'success' i have only
success: function(res){ console.log(res);}
In my case (when using "jquery 1.9.1"), adding dataType: "json" solved the "parsererror" problem (I didn't specify dataType before and that problem occurred).
I had a similar problem.
I called in AJAX a REST service with POST method and got back :
arguments[0] = status 200 (OK) | arguments[1] = "parseerror" | arguments[2] = "Invalid JSON :"
My server method returned a "void" value. To resolve the problem, I replaced it by a Boolean value for example.
I have a problem with a master page containing a asp:textbox that I'm trying to access using jQuery. I have read lot sof thread regarding this and tried all the different approaches I have seen, but regardless, the end result end up as Undefined.
This is the relevant part of the MasterPage code:
<p><asp:Label ID="Label1" AssociatedControlID="osxinputfrom" runat="server">Navn</asp:Label><asp:TextBox CssClass="osxinputform" ID="osxinputfrom" runat="server"></asp:TextBox></p>
When I click the button, the following code from a jQuery .js file is run:
show: function(d) {
$('#osx-modal-content .osxsubmitbutton').click(function (e) {
e.preventDefault();
if (OSX.validate()){
$('#osx-modal-data').fadeOut(200);
d.container.animate(
{height:80},
500,
function () {
$('#osx-modal-data').html("<h2>Sender...</h2>").fadeIn(250, function () {
$.ajax({
type: "POST",
url: "Default.aspx/GetDate",
data: "{'from':'" + $("#osxinputfrom").val() + "','mailaddress':'" + $("#osxinputmail").val() + "','header':'Test3','message':'Test4'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
$('#osx-modal-data').fadeOut(200, function () {
$('#osx-modal-data').html('<h2>Meldingen er sendt!</h2>');
$('#osx-modal-data').fadeIn(200);
});
},
error: function(msg){
$('#osx-modal-data').fadeOut(200, function () {
$('#osx-modal-data').html('<h2>Feil oppstod ved sending av melding!</h2>');
$('#osx-modal-data').fadeIn(200);
});
}
});
});
}
);
}
else{
$('#osxinputstatus').fadeOut(250, function () {
$('#osxinputstatus').html('<p id="osxinputstatus">' + OSX.message + '</a>');
$('#osxinputstatus').fadeIn(250);
});
}
});
},
So the problem here is that $("#osxinputfrom").val() evaluated to Undefined. I understand that the masterpage will add some prefix to the ID, so I tried using the ID from the page when it's run that ends up as ct100_osxinputfrom, and I also tried some other hinds that I found while searching like $("#<%=osxinputfrom.ClientID%>"), but it ends up as Undefined in the method that is called from the jQuery ajax method anyway. The third and fourth parameters to the ajay function that is hardcoded as Test3 and Test4 comes fine in the C# backend method.
So my question is simply: How can I rewrite the jQuery selector to fetch the correct value from the textbox? (before I used master pages it worked fine by the way)
Best regards
Daemon
It will be abit slower but why dont you try adding cssclass="bla" to your label and then get it with $('.bla').val(); ?
You should use the attribute ends with selector
Link
it would be $("id$='osxinputfrom'")
I want to run function inside web service (.asmx file)
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: '/Admin/WebSrvcs/Management.asmx/f_SearchLabel',
data: "{_sQuery:'" + obj.value + "'}",
dataType: "json",
But I don't know where will be my root url(http://localhost:4399/VirDir or something else it may be) address inside js file. And i need to reach root folder of application to find asmx file.
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: 'http://localhost:4399/virDir/Admin/WebSrvcs/Management.asmx/f_SearchLabel',
data: "{_sQuery:'" + obj.value + "'}",
dataType: "json",
I am working on Visual Studio 2008 and building web site with C#.
any help would be greatly appreciated
If you're using Master Pages then this becomes handy:
In the HEAD of Master Page:
<script type="text/javascript">
var baseUrl = '<%# ResolveUrl("~/") %>';
function ResolveUrl(url) {
if (url.indexOf("~/") == 0) {
url = baseUrl + url.substring(2);
}
return url;
}
</script>
In the Master Page .cs page:
protected void Page_Load(object sender, EventArgs e)
{
Page.Header.DataBind();
}
Then in your javascript:
ResolveUrl("~/Admin/WebSrvcs/Management.asmx/f_SearchLabel")
Maybe Im missing something, but if the javascript and the page are on the same server you can just use js to do something like this:
<script>
var pd = parent.document;
var location = pd.location.protocol + "//" + pd.location.host;
alert(location);
</script>
Also, you could write an HTTP handler for your javascript, and when the request comes in, you could fill in a variable by getting the full url of the request.
internal static string GetFullPath(HttpRequest request)
{
Uri uri = request.Url;
string fullUrl = String.Format("{0}{1}{2}{3}", (request.IsSecureConnection) ? "https://" : "http://",
uri.Host, (uri.IsDefaultPort) ? "" : String.Format(":{0}", uri.Port), uri.AbsolutePath);
Int32 index = fullUrl.LastIndexOf("/");
fullUrl = fullUrl.Remove(index + 1, (fullUrl.Length - 1) - index);
return fullUrl;
}
There are some ways you could do this.
One would be to iterate over the <script> elements on the page and check if the src attribute contains the desired script name (e.g. <script src="my/js/dir/myScript.js"></script>) and then extract the path you want.
Although this could be an easy way to port things across other servers, you could have the problem that "myScript.js" could be included more than once in different locations, so it wouldn't be that much reliable.
Another way to do this would be to include some sort of configuration file where you could set up your application settings, using something like this:
File: app-config.js
var AppConfig = {
"someImportantPath" : "some/important/path",
"anotherPath" : "another/path"
}
And the you would use this global variable across your application.