Calling different method from .ashx file through jQuery Ajax request - c#

I'm working on an ASP.NET Web Forms application where in the front end I have jquery DataTable and it was a bit difficult at first to operate with the queries from and to the dataTable I saw an example where .ashx file was used for this purposed and it was working fine for me too so I end up using .ashx file to deal with my dataTable however now I need to make some Ajax requests from different places and till now I was writing all the code inside here:
public class TData : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
// Those parameters are sent by the plugin
var iDisplayLength = int.Parse(context.Request["iDisplayLength"]);
//more code...
}
}
but it's getting harder to keep all this logic in one place so I want to call different methods but at the same time keeping them at the same class Tdata so all the logic for the dataTable is kept in one place.
I tried this:
$.ajax({
url: "/TData.ashx",
type: "GET",
data: { method: 'Test', args: { blabla: 'blabla' } },
});
with this code on the server side:
public object Test(string blabla)
{
return string.Format("Hello {0}!", blabla);
}
but this method actually is never called and it seems that using this syntax the request is going directly to public void ProcessRequest(HttpContext context). I am using .NET 4.5 so is there a way to add additional methods in the same class and call them with jQuery Ajax from the client side?

If you really want to stick with the *.ashx-handler you could redirect the flow based on your method parameter:
public class TData : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
switch (context.Request["method"])
{
case "test":
Test(context);
break;
//other methods
default:
throw new ArgumentException("unknown method");
}
}
public void Test(HttpContext context)
{
// Those parameters are sent by the plugin
var iDisplayLength = int.Parse(context.Request["iDisplayLength"]);
//more code...
context.Response.Write(String.Format("Hello {0}!", blabla));
}
}

Related

C# .Net Core Web API Check CustomSignature

I am new the API in general, let me give you the background of the API and what I want it to do.
I have a API have that are external facing and so every incoming request are required to check the signature from header. literality my code in every controller call are checking the signature and created many duplicated code.
my question is how can reduces those duplicated code ? do I use Custom Attributes, or AuthorizeAttribute
here are some of the example code:
[Route("[controller]")]
[ApiController]
public class ExampleController : ControllerBase
{
public async Task<Result> Call_1(Rquest request)
{
string signaturel;
signature = Util.getHeaderSignature(request);
if(unit.IsSinatureValid(signaturel, someVar1, someVar2))
{
(My logic)
}
else{ return "InvalidSinaturemessage" }
}
public async Task<Result> Call_2(Rquest request)
{
string signaturel;
signature = Util.getHeaderSignature(request);
if(unit.IsSinatureValid(signaturel, someVar1, someVar2))
{
(My logic)
}
else{ return "InvalidSinaturemessage" }
}
}
above code is just for showing, the actual Sinature checking logic is around 20 lines of code on every single controller method.
Yes, you can do that using action filters. It's described in documentation
Put your code for checking into OnActionExecuting method. So, you can write Result in the action filter if the signature isn't valid.
In case you need specific result structure you can create your own ObjectResult:
public class ForbiddenObjectResult : ObjectResult
{
public string Message { get; private set; }
public ForbiddenObjectResult(object value, string message)
: base(value)
{
StatusCode = StatusCodes.Status403Forbidden;
Message = message;
}
}
...
string signaturel;
signature = Util.getHeaderSignature(context.HttpContext.Request);
if(!unit.IsSinatureValid(signaturel, someVar1, someVar2))
{
context.Result = new ForbiddenObjectResult(filterContext.ModelState, "InvalidSinaturemessage");
}
And to register it for all your endpoints(if needed):
services.AddControllersWithViews(options =>
{
options.Filters.Add<YourActionFilter>();
});
You can use token based authentication or filter method. For reference
Token based authentication
Custom Filter

It is possible to intercept Response.Write with own code in ASP.NET

In my project I have a lot of handlers, each of it has hundreds of functions.
public class DataHandler1 : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
switch (CommandName)
{
case "GetTime":
GetTime(context);
break;
....
}
}
private void GetTime(HttpContext context)
{
string str = ...;
context.Response.Write(str);
}
Each function reads the Request.QueryString and writes result as Response.Write.
Initially idea of this handlers was be call it only from JS, but now I need perform this handlers from server side (ASP.NET Classic). It's impossible to rewrite huge amount of functions or create double of this code for server side perform.
So, the best solution looks like an overload and override of Response.Write to receive simple string in my own code something in this way.
var X = new DataHandler1(context, myCurrentUserDM);
string ResponseWriteResult = X.GetTime.RequestQueryString("?a=1&b=2&c=3");
Is this possible?

how to add delegate class for service manager class when calling soap service in c#?

First of all, I want to share my scenario what i want to build -
Scenario:
I am building a client app using wpf. In some cases, I need to call a web service to get data from the server. In order to do this, I added a web reference using wsld url. And I created a ServiceManager class that will call service method. For security reason, I need to add some header info at soap xml request for example, UserToken, SAML Token and so on. I can this from my ServiceManager class. But I want to add another class which will be called before sending request to the server. In that class, I will do something like adding security header to soap xml request with request and then send it to the server.
I used SOAP Extension to fulfill my purpose and it works well. But the problem is, every-time I need to add annotation in Reference.cs (for each web service reference) file at top of the service method. I believe that there is some other easiest way to make this working better than SOAP Extension. Is there any way where I can only call the service and a delegate class will be called automatically and I don't need to add any annotation to the reference file? I will share my sample code here.
ServiceManage class:
public class ServiceManager
{
public UserDataService dataService; //web service added at Web Reference
public ServiceManager()
{
dataService = new UserDataService();
getUserServiceRequest rqst = new getUserServiceRequest();
getUserServiceResponse resp = dataService.getUser(rqst);
}
}
Reference.cs
[TraceExtensionAttribute(Name = "First")]
public getUserServiceResponse getUser([System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] getUserServiceRequest request) {
object[] results = this.Invoke("getUser", new object[] {
request});
return ((getUserServiceResponse)(results[0]));
}
TraceExtensionAttribute.cs
[AttributeUsage(AttributeTargets.Method)]
public class TraceExtensionAttribute : SoapExtensionAttribute
{
private string mstrName = null;
public override Type ExtensionType
{
get { return typeof(TraceExtension); }
}
public override int Priority
{
get { return 1; }
set { }
}
public string Name
{
get { return mstrName; }
set { mstrName = value; }
}
}
TraceExtension.cs
public class TraceExtension : SoapExtension
{
public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attr){//..do something}
public override void Initialize(object initializer){//..do something}
public override Stream ChainStream(Stream stream){//...do something}
public override void ProcessMessage(SoapMessage message) {//..do something}
}
Finally, I found the solution. Just through out Web Reference and add Service Reference instead. Then go to the following link. It works for me.

Servicestack - Order of Operations, Validation and Request Filters

I detected a problem in the RequestFilter execution order.
The ValidationFeature in ServiceStack is a Plugin that just registers a Global Request Filter. The Order of Operations points out that Global Request Filters are executed after Filter Attributes with a Priority <0 and before Filter Attributes with a Priority >=0
My BasicAuth filter has -100 priority, and in fact everything goes well if the Service is annotated at class level, but it fails when the annotation is at method level, with the authentication filter being executed after.
I am using 3.9.70
Is there any quick fix for this? Thanks
When you add the annotation at method level then you are creating an Action Request Filter (because you are adding the annotation to an action method) which in the Order of Operations is operation 8, after the other filters have run.
5: Request Filter Attributes with Priority < 0 gets executed
6: Then any Global Request Filters get executed
7: Followed by Request Filter Attributes with Priority >= 0
8: Action Request Filters (New API only)
The best workaround I can suggest is to reconsider your service structure. I imagine you are having these difficulties because you are adding unauthenticated api methods alongside your secure api methods, and thus are using method level attributes to control authentication. So you are presumably doing something like this Your classes and attributes will be different, this is just exemplar:
public class MyService : Service
{
// Unauthenticated API method
public object Get(GetPublicData request)
{
return {};
}
// Secure API method
[MyBasicAuth] // <- Checks user has permission to run this method
public object Get(GetSecureData request)
{
return {};
}
}
I would do this differently, and separate your insecure and secure methods into 2 services. So I use this:
// Wrap in an outer class, then you can still register AppHost with `typeof(MyService).Assembly`
public partial class MyService
{
public class MyPublicService : Service
{
public object Get(GetPublicData request)
{
return {};
}
}
[MyBasicAuth] // <- Check is now class level, can run as expected before Validation
public class MySecureService : Service
{
public object Get(GetSecureData request)
{
return {};
}
}
}
Solution - Deferred Validation:
You can solve your execution order problem by creating your own custom validation feature, which will allow you to defer the validation process. I have created a fully functional self hosted ServiceStack v3 application that demonstrates this.
Full source code here.
Essentially instead of adding the standard ValidationFeature plugin we implement a slightly modified version:
public class MyValidationFeature : IPlugin
{
static readonly ILog Log = LogManager.GetLogger(typeof(MyValidationFeature));
public void Register(IAppHost appHost)
{
// Registers to use your custom validation filter instead of the standard one.
if(!appHost.RequestFilters.Contains(MyValidationFilters.RequestFilter))
appHost.RequestFilters.Add(MyValidationFilters.RequestFilter);
}
}
public static class MyValidationFilters
{
public static void RequestFilter(IHttpRequest req, IHttpResponse res, object requestDto)
{
// Determine if the Request DTO type has a MyRoleAttribute.
// If it does not, run the validation normally. Otherwise defer doing that, it will happen after MyRoleAttribute.
if(!requestDto.GetType().HasAttribute<MyRoleAttribute>()){
Console.WriteLine("Running Validation");
ValidationFilters.RequestFilter(req, res, requestDto);
return;
}
Console.WriteLine("Deferring Validation until Roles are checked");
}
}
Configure to use our plugin:
// Configure to use our custom Validation Feature (MyValidationFeature)
Plugins.Add(new MyValidationFeature());
Then we need to create our custom attribute. Your attribute will be different of course. The key thing you need to do is call ValidationFilters.RequestFilter(req, res, requestDto); if you are satisfied the user has the required role and meets your conditions.
public class MyRoleAttribute : RequestFilterAttribute
{
readonly string[] _roles;
public MyRoleAttribute(params string[] roles)
{
_roles = roles;
}
#region implemented abstract members of RequestFilterAttribute
public override void Execute(IHttpRequest req, IHttpResponse res, object requestDto)
{
Console.WriteLine("Checking for required role");
// Replace with your actual role checking code
var role = req.GetParam("role");
if(role == null || !_roles.Contains(role))
throw HttpError.Unauthorized("You don't have the correct role");
Console.WriteLine("Has required role");
// Perform the deferred validation
Console.WriteLine("Running Validation");
ValidationFilters.RequestFilter(req, res, requestDto);
}
#endregion
}
For this to work we need to apply our custom attribute on the DTO route not the action method. So this will be slightly different to how you are doing it now, but should still be flexible.
[Route("/HaveChristmas", "GET")]
[MyRole("Santa","Rudolph","MrsClaus")] // Notice our custom MyRole attribute.
public class HaveChristmasRequest {}
[Route("/EasterEgg", "GET")]
[MyRole("Easterbunny")]
public class GetEasterEggRequest {}
[Route("/EinsteinsBirthday", "GET")]
public class EinsteinsBirthdayRequest {}
Then your service would look something like this:
public class TestController : Service
{
// Roles: Santa, Rudolph, MrsClaus
public object Get(HaveChristmasRequest request)
{
return new { Presents = "Toy Car, Teddy Bear, Xbox" };
}
// Roles: Easterbunny
public object Get(GetEasterEggRequest request)
{
return new { EasterEgg = "Chocolate" };
}
// No roles required
public object Get(EinsteinsBirthdayRequest request)
{
return new { Birthdate = new DateTime(1879, 3, 14) };
}
}
So when we call the route /EinsteinsBirthday which does not have a MyRole attribute the validation will be called normally, as if using the standard ValidationFeature.
If we call the route /HaveChristmas?role=Santa then our validation plugin will determine that the DTO has our attribute and not run. Then our attribute filter triggers and it will trigger the validation to run. Thus the order is correct.

progressivelly updating model in asp.net mvc

I have a long db networking call and I want to populate my model in chunks. We are talking about asp.net MVC.
I have a vague idea that each time a new chunk is available I should trigger the model.Bind()
but I don't know how to do the plumbing between
a) the service which is providing the data in chunks- it's implemented using the event pattern- each time a new chunk is available an event is triggered, but which event ? It should hold a reference to the model?
b) the data which will be bound to the model ( i suppose it should not be an bind(), but an addition to some collection)
c) if everything is ok in steps a and b, then the changes will be propagated to the view without further a do?
You could use long polling with a hidden iframe and chunked transfer encoding from the server which will spit <script> tags as data becomes available. In this script tag you could invoke a custom callback javascript function that will take care to format the results.
UPDATE:
As requested in the comments section here's a sample implementation of a long polling technique using a hidden iframe.
Let's suppose that you have some model:
public class MyViewModel
{
public string Foo { get; set; }
}
and that you have a service that returns this model in chunks and notifies the caller that a chunk is available using events:
public class MyService
{
public void GetModels(Action<MyViewModel, object> onModelAvailable, object state, Action onComplete)
{
Task.Factory.StartNew(x =>
{
try
{
for (int i = 0; i < 10; i++)
{
onModelAvailable(new MyViewModel
{
Foo = "foo " + i
}, x);
Thread.Sleep(1000);
}
}
finally
{
onComplete();
}
}, state);
}
}
Now, we could have the following controller:
public class HomeController : AsyncController
{
public ActionResult Index()
{
return View();
}
public ActionResult LongPoll()
{
var service = new MyService();
return new MyActionResult(service);
}
}
and the following view:
<script type="text/javascript">
// we define a callback function which will be invoked
// when a chunk is available from the server
var callback = function (model) {
// the model variable passed here will represent the chunk
$($('<div/>', {
html: model.Foo
})).appendTo('#result');
};
</script>
<iframe style="display:none;" src="#Url.Action("longpoll")"></iframe>
<div id="result"></div>
Now the last part of course is the implementation of the custom action result which will do the chunked transfer:
public class MyActionResult : ActionResult
{
private readonly MyService _service;
public MyActionResult(MyService service)
{
_service = service;
}
public override void ExecuteResult(ControllerContext context)
{
var response = context.HttpContext.Response;
response.BufferOutput = true;
response.ContentType = "text/html";
var wait = new ManualResetEvent(false);
_service.GetModels((model, state) =>
{
var httpResponse = (HttpResponseBase)state;
httpResponse.BufferOutput = true;
httpResponse.ContentType = "text/html";
var serializer = new JavaScriptSerializer();
var script = string.Format(
"<script type=\"text/javascript\">window.parent.callback({0});</script>",
serializer.Serialize(model)
);
httpResponse.Write(script);
httpResponse.Flush();
},
response,
() =>
{
wait.Set();
});
wait.WaitOne();
}
}
The simplest solution is to use polling, just some ajax call every n-seconds to check if new data is available. Downsides to this approach: latency, server load. Advantages: rather simple to implement.
A better but much more involved solution is to use something like long-polling, web-sockets, etc.. If this feature is worth the trouble then take a look at Signal-R, which is an async signaling library for ASP.NET to help you build real-time, multi-user interactive web applications. Adding it to an ASP.NET MVC 3 web application is very straightforward. This is a good intro to the library: Asynchronous Scalable Web Applications With Realtime Persistent Long running Connections With SignalR

Categories