asp.net webservice cross domain call for json, - asp.net

a small but very annoying problem. I am trying to use jQuery JSON call with asp.net web service. It all works fine with the below HttpModule if I call the web service without any arguments. As soon as I try and send a value from the client side, Module gets executed but the process doesn't pass over to the actual webservice method and returns with a server side 500 error. If we remove the module from the middle, then the method gets executed perfectly fine with parameter but then the response comes back in the XML format instead of JSON so we are helpless to use the Module.
----------- Jquery Call ---------------------
var dd = { 'name': 'pakistan' };
$(document).ready(function () {
$.getJSON("http://localhost:59271/Testing/shows-app.asmx/HelloWorld?callback=?",
dd,
function (data) {
val = JSON.parse(data.d)
$("#content").html(val.response);
});
});
------------ HttpModule -------------
private const string JSON_CONTENT_TYPE = "application/json; charset=utf-8";
public void Dispose()
{
}
public void Init(HttpApplication app)
{
app.BeginRequest += OnBeginRequest;
app.EndRequest += new EventHandler(OnEndRequest);
}
public void OnBeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpRequest request = app.Request;
//Make sure we only apply to our Web Service
if (request.Url.AbsolutePath.ToLower().Contains("-app."))
{
var method = app.Context.Request.Headers["REQUEST_METHOD"];
if (string.IsNullOrEmpty(app.Context.Request.ContentType))
{
app.Context.Request.ContentType = JSON_CONTENT_TYPE;
}
app.Context.Response.Write(app.Context.Request.Params["callback"] + "(");
var method2 = app.Context.Request.Headers["REQUEST_METHOD"];
}
}
void OnEndRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpRequest request = app.Request;
if (request.Url.AbsolutePath.ToLower().Contains("-app."))
{
app.Context.Response.Write(")");
app.Context.Response.ContentType = "application/json";
}
}
----------- Webservice ---------------------
[WebMethod]
[System.Web.Script.Services.ScriptMethod(UseHttpGet = true, ResponseFormat = System.Web.Script.Services.ResponseFormat.Json)]
public string HelloWorld(string name)
{
var json = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(new
{
response = "Pakistan " + " Zindabad"
});
return json;
//string jsoncallback = HttpContext.Current.Request["callback"];
//return string.Format("{0}({1})", jsoncallback, json);
}
Please remember that, if we remove the module from the middle, then the method gets executed perfectly fine with parameter but then the response comes back in the XML format instead of JSON so we are helpless to use the Module.
Thanks a bunch in advance.

Related

Upgrading from asp net mvc to asp core + angular

I'm upgrading an old application in asp net mvc to a new version with asp core + angular 7. In the old app, we had an external service calling our api, and sending the auth token in the URL because it couldn't do otherwise.
I intercept it to inject the token in the header like this:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_PreSendRequestHeaders()
{
Response.Headers.Remove("X-Frame-Options");
Response.AddHeader("X-Frame-Options", "AllowAll");
}
private void Application_BeginRequest(object sender, EventArgs e)
{
var header = HttpContext.Current.Request;
var url = HttpContext.Current.Request.Url;
var Params = HttpContext.Current.Request.Params;
if (ReferenceEquals(null, HttpContext.Current.Request.Headers["Authorization"]))
{
var token = HttpContext.Current.Request.Params["access_token"];
if (!String.IsNullOrEmpty(token))
{
HttpContext.Current.Request.Headers.Add("Authorization", "Bearer " + token);
}
}
}
protected void Application_Start()
{
//DashboardConfig.RegisterService(RouteTable.Routes);
DevExtremeBundleConfig.RegisterBundles(BundleTable.Bundles);
C_Interface_Meta.IntialiserBdd();
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new RazorViewEngine());
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
GlobalConfiguration.Configure(WebApiConfig.Register);
RouteConfig.RegisterRoutes(RouteTable.Routes);
//GlobalConfiguration.Configure(WebApiConfig.Register);
ASPxWebControl.CallbackError += Application_Error;
BundleConfig.RegisterBundles(BundleTable.Bundles);
DisableApplicationInsightsOnDebug();
}
/// <summary>
/// Disables the application insights locally.
/// </summary>
[Conditional("DEBUG")]
private static void DisableApplicationInsightsOnDebug()
{
TelemetryConfiguration.Active.DisableTelemetry = true;
}
public static void Register(HttpConfiguration config)
{
config.Filters.Add(new PrettyPrintFilterAttribute());
}
protected void Application_Error(object sender, EventArgs e)
{
Exception exception = HttpContext.Current.Server.GetLastError();
if (exception is HttpUnhandledException)
exception = exception.InnerException;
AddToLog(exception.Message, exception.StackTrace);
}
public static void AddToLog(string message, string stackTrace)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine(DateTime.Now.ToLocalTime().ToString());
sb.AppendLine(message);
sb.AppendLine();
sb.AppendLine("Source File: " + HttpContext.Current.Request.RawUrl);
sb.AppendLine();
sb.AppendLine("Stack Trace: ");
sb.AppendLine(stackTrace);
for (int i = 0; i < 150; i++)
sb.Append("-");
sb.AppendLine();
HttpContext.Current.Application["Log"] += sb.ToString();
sb.AppendLine();
}
}
What is the equivalent way for doing that in an angular asp core application? After much searching, I didn't find anything.
Sounds like you're using JWT bearer and sending the token via query string. If that's the case, you could simply use an event handler OnMessageReceived to set the token dynamically :
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options=> {
options.TokenValidationParameters = new TokenValidationParameters{
// ValidIssuer, ValidAudience, IssuerSigningKey , ...
};
options.Events = new JwtBearerEvents() {
OnMessageReceived = async (context) =>{
// get bearer From Header/QueryString as you like
var bearer=context.HttpContext.Request.Query["access_token"].FirstOrDefault();
if(!String.IsNullOrEmpty(bearer)){
context.Token = bearer; // simply set the token
}
},
};
});
// other services ...
}
Or as suggested by Razgort, you could register a middleware to set the token.
Be careful for the order of middlewares.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// register it before other middlewares that rely on this token
app.Use(async(context,next)=>{
var bearer = context.Request.Headers["Authorization"].FirstOrDefault();
if(bearer==null){
bearer=context.Request.Query["access_token"].FirstOrDefault();
if(!String.IsNullOrEmpty(bearer)){
context.Request.Headers.Add("Authorization", "Bearer " + bearer);
}
}
await next();
});
// other middlewares ...
app.UseMvc(...)//
}
I think you are looking for angular interceptors, which pretty much doest the same thing. You want to inject the tokens something like this:
#Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private auth: AuthService) {}
intercept(req: HttpRequest<any>, next: HttpHandler) {
// Get the auth token from the service.
const authToken = this.auth.getAuthorizationToken();
// Clone the request and replace the original headers with
// cloned headers, updated with the authorization.
const authReq = req.clone({
headers: req.headers.set('Authorization', authToken)
});
// send cloned request with header to the next handler.
return next.handle(authReq);
}
}

Accessing session through pagemethods throw webServiceError when connecting to SQL Server

I have a problem with accessing values in the session through pagemethods when I try connecting to SQL Server.
I have uploadEngin.aspx page for uploading files and for monitoring the upload state I store the state value (like 10%) in session. In the uploadEngin.aspx page I am connecting to SQL Server to get the valid extension for files. I have a basic problem. Example below show a sample code:
uploadEngin:
protected void Page_Load(object sender, EventArgs e)
{
this.Session["s"] = "hello";
if (!IsPostBack)
{
admin.app.core.attachment.AttachmentType att = new app.core.attachment.AttachmentType();
att.GetExtentionAndMainPath("Image");
}
}
[System.Web.Services.WebMethod(EnableSession = true)]
public static String g()
{
return HttpContext.Current.Session["s"].ToString();
}
Javascript:
(function () {
window.onload = function () {
PageMethods.g(function (r) { alert(r); }, function (r) {
console.log(r);
});
}
})();
GetExtentionAndMainPath:
public String[] GetExtentionAndMainPath(String name)
{
String[] ext =new String[2];
String x = name;
UInt64 id = FindIdByName(x);
DataTable dt = new DataAccess().ExecuteSelect("Select_ano_attachmentType", CommandType.StoredProcedure, new DataParam("#id", id, SqlDbType.BigInt));
if (dt.Rows.Count > 0)
{
ext[0] = dt.Rows[0]["attachmentType_validExtention"].ToString();
ext[1]= dt.Rows[0]["attachmentType_mainPath"].ToString();
}
return ext;
}
Without code inside if(!isPostBack) everything works fine and I see the "hello" message. When I use that code however (connecting to SQL Server to get the valid extension), I get
WebServiceError: Object reference not set to an instance of an object
How should I solve this problem?
You need to set EnableSession property on your WebMethod attribute in order to access Session values in your web method.
[WebMethod(EnableSession = true)]
public static String g()
{
return HttpContext.Current.Session["s"].ToString();
}
For more details, please refer the MSDN link.

IHttpModule filter write method is not called asp.net

I'm trying to change the response to get jsonp(for web services), but the problem is that the write method is never ever called only flush() is called at the end, the url is
localhost:8080/api/employees
its calling web api and employee is a controller file,
Controller Method which is called
public List<Models.Employee> Get() {
var employees = from e in _context.Employees
select new Models.Employee {
Id = e.EmployeeID,
FirstName = e.FirstName,
LastName = e.LastName
};
return employees.ToList();
}
IHTTPModule Method which is invoked
public void OnReleaseRequestState(object sender, EventArgs e)
{
HttpResponse response = HttpContext.Current.Response;
if (response.ContentType != JSON_CONTENT_TYPE && response.ContentType != JSON_CONTENT_TYPE1) return;
//response.ContentEncoding =
// char[] c = { 'd', 's', 'w', 'w' };
response.Filter = new JsonResponseFilter(response.Filter);
//response.Cache.
// response.ClearContent();
// response.Write(c, 0, 4);
// response.Flush();
}
Now JsonResponseFilter.write is not called thats the issue, anyone kindly reply back to resolve it
You are doing it all wrong. Don't use any IHttpModules. The correct way to achieve this in the Web API is to use a custom media formatter. For example there's a JsonpFormatter that you could integrate in Application_Start and which will enable JSONP for your web methods:
var config = GlobalConfiguration.Configuration;
config.Formatters.Insert(0, new JsonpMediaTypeFormatter());

Async calls in WP7

I have been experimenting with WP7 apps today and have hit a bit of a wall.
I like to have seperation between the UI and the main app code but Ive hit a wall.
I have succesfully implemented a webclient request and gotten a result, but because the call is async I dont know how to pass this backup to the UI level. I cannot seem to hack in a wait for response to complete or anything.
I must be doing something wrong.
(this is the xbox360Voice library that I have for download on my website: http://www.jamesstuddart.co.uk/Projects/ASP.Net/Xbox_Feeds/ which I am porting to WP7 as a test)
here is the backend code snippet:
internal const string BaseUrlFormat = "http://www.360voice.com/api/gamertag-profile.asp?tag={0}";
internal static string ResponseXml { get; set; }
internal static WebClient Client = new WebClient();
public static XboxGamer? GetGamer(string gamerTag)
{
var url = string.Format(BaseUrlFormat, gamerTag);
var response = GetResponse(url, null, null);
return SerializeResponse(response);
}
internal static XboxGamer? SerializeResponse(string response)
{
if (string.IsNullOrEmpty(response))
{
return null;
}
var tempGamer = new XboxGamer();
var gamer = (XboxGamer)SerializationMethods.Deserialize(tempGamer, response);
return gamer;
}
internal static string GetResponse(string url, string userName, string password)
{
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))
{
Client.Credentials = new NetworkCredential(userName, password);
}
try
{
Client.DownloadStringCompleted += ClientDownloadStringCompleted;
Client.DownloadStringAsync(new Uri(url));
return ResponseXml;
}
catch (Exception ex)
{
return null;
}
}
internal static void ClientDownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
ResponseXml = e.Result;
}
}
and this is the front end code:
public void GetGamerDetails()
{
var xboxManager = XboxFactory.GetXboxManager("DarkV1p3r");
var xboxGamer = xboxManager.GetGamer();
if (xboxGamer.HasValue)
{
var profile = xboxGamer.Value.Profile[0];
imgAvatar.Source = new BitmapImage(new Uri(profile.ProfilePictureMiniUrl));
txtUserName.Text = profile.GamerTag;
txtGamerScore.Text = int.Parse(profile.GamerScore).ToString("G 0,000");
txtZone.Text = profile.PlayerZone;
}
else
{
txtUserName.Text = "Failed to load data";
}
}
Now I understand I need to place something in ClientDownloadStringCompleted but I am unsure what.
The problem you have is that as soon as an asynchronous operation is introduced in to the code path the entire code path needs to become asynchronous.
Because GetResponse calls DownloadStringAsync it must become asynchronous, it can't return a string, it can only do that on a callback
Because GetGamer calls GetResponse which is now asynchronous it can't return a XboxGamer, it can only do that on a callback
Because GetGamerDetails calls GetGamer which is now asynchronous it can't continue with its code following the call, it can only do that after it has received a call back from GetGamer.
Because GetGamerDetails is now asynchronous anything call it must also acknowledge this behaviour.
.... this continues all the way up to the top of the chain where a user event will have occured.
Here is some air code that knocks some asynchronicity in to the code.
public static void GetGamer(string gamerTag, Action<XboxGamer?> completed)
{
var url = string.Format(BaseUrlFormat, gamerTag);
var response = GetResponse(url, null, null, (response) =>
{
completed(SerializeResponse(response));
});
}
internal static string GetResponse(string url, string userName, string password, Action<string> completed)
{
WebClient client = new WebClient();
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))
{
client.Credentials = new NetworkCredential(userName, password);
}
try
{
client.DownloadStringCompleted += (s, args) =>
{
// Messy error handling needed here, out of scope
completed(args.Result);
};
client.DownloadStringAsync(new Uri(url));
}
catch
{
completed(null);
}
}
public void GetGamerDetails()
{
var xboxManager = XboxFactory.GetXboxManager("DarkV1p3r");
xboxManager.GetGamer( (xboxGamer) =>
{
// Need to move to the main UI thread.
Dispatcher.BeginInvoke(new Action<XboxGamer?>(DisplayGamerDetails), xboxGamer);
});
}
void DisplayGamerDetails(XboxGamer? xboxGamer)
{
if (xboxGamer.HasValue)
{
var profile = xboxGamer.Value.Profile[0];
imgAvatar.Source = new BitmapImage(new Uri(profile.ProfilePictureMiniUrl));
txtUserName.Text = profile.GamerTag;
txtGamerScore.Text = int.Parse(profile.GamerScore).ToString("G 0,000");
txtZone.Text = profile.PlayerZone;
}
else
{
txtUserName.Text = "Failed to load data";
}
}
As you can see async programming can get realy messy.
You generally have 2 options. Either you expose your backend code as an async API as well, or you need to wait for the call to complete in GetResponse.
Doing it the async way would mean starting the process one place, then return, and have the UI update when data is available. This is generally the preferred way, since calling a blocking method on the UI thread will make your app seem unresponsive as long as the method is running.
I think the "Silverlight Way" would be to use databinding. Your XboxGamer object should implement the INotifyPropertyChanged interface. When you call GetGamer() it returns immediately with an "empty" XboxGamer object (maybe with GamerTag=="Loading..." or something). In your ClientDownloadStringCompleted handler you should deserialize the returned XML and then fire the INotifyPropertyChanged.PropertyChanged event.
If you look at the "Windows Phone Databound Application" project template in the SDK, the ItemViewModel class is implemented this way.
Here is how you can expose asynchronous features to any type on WP7.

Calling a non static method in Server Side by a Client Side Function

I can get an object from the server side by using static receive callbackresult methods from server side.
But I want to run a non-static method in my page which populates an ajax accordion by calling a client side function.
The object I am calling from server side is a complex object which I can't use in client side if I get it by callbackresults.
Is there any other solution that I can run a non static method in an aspx file by a client side control ?
Codes I am using so far ...
function ReceiveServerData(arg, context) {
//Message.innerText = "Date from server: " + arg;
}
#region ICallbackEventHandler Members
public void RaiseCallbackEvent(String eventArgument)
{
// Processes a callback event on the server using the event
// argument from the client.
Insert(); // this is running, but doesnt work !
//printAlternativesFromAirport(eventArgument);
}
public string GetCallbackResult()
{
// Returns the results of a callback event to the client.
return null;
}
#endregion
protected void Page_Load(object sender, EventArgs e)
{
ClientScriptManager cm = Page.ClientScript;
String cbReference = cm.GetCallbackEventReference(this, "arg",
"ReceiveServerData", "");
String callbackScript = "function CallServer(arg, context) {" +
cbReference + "; }";
cm.RegisterClientScriptBlock(this.GetType(),
"CallServer", callbackScript, true);
}
yes, you need to create a handler that will create the entire context needed for the page, which will run a full page life cycle ect, and is more recommended when you want to retrieve something like a user control or something big.
public void ProcessRequest(HttpContext context)
{
context.Response.Write(RenderView("~/_controltemplates/15/myDir/Templates/myUC.ascx"));
}
public static string RenderView(string path)
{
try
{
Page pageHolder = new Page();
UserControl viewControl = (UserControl)pageHolder.LoadControl(path);
pageHolder.Controls.Add(viewControl);
StringWriter result = new StringWriter();
Log.Application.Debug(LOGPREFIX + "RenderView before Execute");
HttpContext.Current.Server.Execute(pageHolder, result, true);
return result.ToString();
}
catch (Exception ex)
{
Log.Application.ErrorException(LOGPREFIX, ex);
throw;
}
}
but i think that it is not what you need, instead i would advice you to make an entity (class) to handle that insert function that will not need any httpContext and run it from a simple handler.
another solution you might need, since maybe you do need all the postback info but do not want to make a full postback is to use AjaxPanel or even clear the Response and send "OK" instead.

Resources