In the new .NET 7.0 framework, things have changed considerably...
This has been asked a gazillion times before and if the .NET Core framework would not break all kinds of backwards compatibility then I would have an easy answer. Too bad a lot of answers are related to .NET 4.9 and older and they just don't work.
So in my minimal Web API I want to do some simple request logging by sending the complete URL as a string to a database. (With some additional information.) So I have the HttpContext class (NOT the HttpContext class) with the Request property of type HttpRequest and it just does not have any method to get the original URL that was requested. Only the various parts which I have to concatenate and hope it resembles the original uri...
So, a useful method like Request.Url is now totally gone and the DisplayUrl helper() isn't providing me everything. It leaves out the QueryString. I need that QueryString also.
And yes, I can concatenate this again to get the value that it originally received and made hidden. It just feels wrong, though. Plus, this method makes the uri suitable to be returned in a header. Again, I want to store it in a database for logging purposes exactly as it originally was!
So now I have to ask something that has been asked a gazillion times before, simply because the latest .NET update breaks things again.
The application I'm working on is a multi-tenant application running on multiple domain names including wildcard subdomains and is used to analyze the amount of traffic I get for new domains that I've registered. The whole API will just generate 404-errorcodes back to the user, but I want the whole URL to get registered to determine if the domain isn't getting any funny requests. (Like hackers trying to access https://owa.example.com/wp-booking.php or https://forum.example.com/default.aspx?g=rsstopic&pg=0&ft=0 or whatever.) I also log the body of the request, the request method, the IP address of the user and the headers that are passed and it cal be used by me to extend a blacklist of users who seem to have malicious intent.
The domains where I use it are often fresh out of quarantine and are just in a wait-state until development starts. (Or until someone takes it over.) Responding with a 404-error should tell users (and hackers) that the site does not exist any more. Most users will be aware that the site is gone so they stop visiting, but various automated (and hacking) tools might still be running so the information tells me what the user is trying to do.
Anyways, I need the full URL with the query string, domain name, protocol and everything else that the client has passed to my server. But .NET 7 is preventing me from access to the original URL which is dumb. And the whole project is basically a single app.Run() statement which always returns a 404 error after logging the request. And yes, slow is fine for this API.
Sigh... Request.Url.AbsoluteUri was such a useful function, but it's gone, making all answers going back 14 years or so obsolete as Request has no Url...
UriHelper.GetDisplayUrl(source) should do the trick:
app.MapGet("test_uri", (HttpContext context) => context.Request.GetDisplayUrl());
Returns http://localhost:5207/test_uri?query=1&test=2 for this url.
So in my minimal Web API I want to do some simple request logging by sending the complete URL as a string to a database.
Minimal APIs support request logging - docs, example. Potentially you can combine it with some logging library which allows writing to database.
Related
I have some kind of a job scheduling implemented which calls a function ProcessJob. Now inside this method I need to generate url to one of my pages i.e DoanloadPage.aspx?some_params. That url is sent to user via email and when user clicks that link, it will take to the page.
The problem here is that I am not generating url in a web request method or I don't have access to the Request object. URL need to be generated in a custom class which is threaded i.e not in a web request.
So I can't go with these solutions:
HostingEnvironment.MapPath("test.aspx");
VirtualPathUtility.ToAbsolute("123.aspx");
HttpContext.Current.Request.Url.Authority;
None of these works because I think they all rely on current request or session somehow. So how do I generate urls for my app inside my code so I can use them anyway I want.
If your method cannot use HttpContext.Current.Request.Url, for example in case it's a background scheduled task, then you can use either of the following options:
In case that your code is hosted in the same ASP.NET application, you can pass the site domain name of the site to your class, in the first request. To do so, you need to handle Application_BeginRequest event and get the domain from HttpContext.Current.Request.Url and then pass it to your class, or store it in an application scope storage. You can find an implementation in this post or the original article.
Note: The code is available in SO, so I don't repeat the code
here.
If your code is not hosted in the same ASP.NET application or if for any reason you don't want to rely on Application_BeginRequest, as another option you can store the site domain name in a setting (like appsettigs in app.condig or web.config if it's web app) and use it in your code.
You can do something like this. Dns.GetHostName will return the name of the computer that is hosting the site. You can use that to check if the site is on a development server.
string domain = "www.productionurl/123.aspx";
if (Dns.GetHostName() == "Development")
{
domain = "www.developmenturl/123.aspx";
}
The Dns.GetHostName() is not the only way to check. You could also use the HostingEnvironment.ApplicationPhysicalPath. You can check that also and see if the path is that of the development server.
My answer is: don't do this. You're building a distributed system, albeit a simple one, and generally speaking it is problematic to introduce coupling between services in a distributed system. So even though it is possible to seed your domain using Application_BeginRequest, you are then tying the behavior of your batch job to your web site. With this arrangement you risk propagating errors and you make deployment of your system more complicated.
A better way to look at this problem is to realize that the core desire is to synchronize the binding of your production site with the URL that is used in your batch job. In many cases an entry in the app.config of your batch would be the best solution, there really isn't any need to introduce code unless you know that your URL will be changing frequently or you will need to scale to many different arbitrary URLs. If you have a need to support changing the URL programmatically, I recommend you look at setting up a distributed configuration system like Consul and read the current URLs from your deployment system for both the IIS binding and the app.config file for your batch. So even in this advanced scenario, there's no direct interaction between your batch and your web site.
I have a program that opens a web browser control and just displays a web page from our server. They can't navigate around or anything.
The users are not allowed to know the credentials required to login, so after some googling on how to log into a server I found this:
http://user_name:password#URL
This is 'hard coded' into the web browsers code. -It works fine.
HOWEVER: Some smart ass managed to grab the credentials by using WireShark which tracks all the packets sent from your machine.
Is there a way I can encrypt this so the users cannot find out?
I've tried other things like using POST but with the way the page was setup, it was proving extremely difficult to get working. -(Its an SSRS Report Manager webpage)
I forgot to include a link to this question: How to encrypt/decrypt the url in C#
^I cannot use this answer as I myself am not allowed to change any of the server setup!
Sorry if this is an awful question, I've tried searching around for the past few days but can't find anything that works.
Perhaps you could work around your issue with a layer of indirection - for example, you could create a simple MVC website that doesn't require any authentication (or indeed, requires some authentication that you fully control) and it is this site that actually makes the request to the SSRS page.
That way you can have full control over how you send authentication, and you need never worry about someone ever getting access to the actual SSRS system. Now if your solution requires the webpage to be interactive then I'm not sure this will work for you, but if it's just a static report, it might be the way to go.
i.e. your flow from the app would be
User logs into your app (or use Windows credentials, etc)
User clicks to request the SSRS page
Your app makes an HTTP request to your MVC application
Your MVC application makes the "real" HTTP request to SSRS (eg via HttpClient, etc) and dumps the result back to the caller (for example,it could write the SSRS response via #HTML.Raw in an MVC View) The credentials for SSRS will therefore never be sent by your app, so you don't need to worry about that problem any more...
Just a thought.
Incidentally, you could take a look here for the various options that SSRS allows for authentication; you may find some method that suits (for e.g Custom authentication) - I know you mentioned you can't change anything on the server so I'm just including it for posterity.
I'm having a strange problem in a Silverlight Business Application that calls an external API. I'm sure it's just one line wrong or something. The API has one call that uses digest authentication and I handle that all myself. My code was working before, but then I began a transition to hosting the backend API and this front-end website on Azure and something must have changed. Now, before the request comes back to my code to handle, the browser is popping up a login dialog of its own. If I cancel out of that dialog, it moves on to my code and authenticates successfully.
It seems as if the browser is handling the request, noticing the 401 status code, and attempting to resolve it itself. But I do register the ClientHttp factory for the http:// prefix as suggested, and the request type that is created is a ClientHttpWebRequest. Like I said, this was all working about a week ago using the same authentication code and everything, so I'm sure it's just going to be some setting. But I'm not sure where that could be and I haven't found anyone else with this problem.
Curiously, when I publish the ASP project to an Azure website, it all looks and acts as expected, but the login doesn't even pop up the dialog. It simply doesn't do anything when I click "login." So that part looks like maybe an unhandled exception is being thrown then it's not telling me about it, but I'm not sure why that would be the case on Azure but not IIS Express.
Basically, I just don't want that dialog coming up. I am inclined to assume that the same problem that's causing that is whatever is making the Azure-hosted version not do anything.
I've done a fair bit of searching and found this question, "How can I supress the browser's authentication dialog?" which seems to be the same issue, but as I stated a few times, this was working just last week. I do have full control of the API and this site, so I could alter some things to make it suppress HTTP statuses and simply return a 200 with details in the content as a substitute, but I'd rather avoid that extra layer of complexity if it really is something simple, as I imagine it is.
After some fiddling, it seems the best way to handle this error is simply to use the WebRequest.Credentials property and populate it, rather than forming my Digest authorization header myself. It isn't exactly what I was going for, but it will do for now. I still don't know why this stopped working in the first place. But what fun is programming if everything goes according to plan?
Once one has a logging and tracing setup using log4net in place for ASP.NET Web API, what are the specific aspects that need to be logged and/or traced?
I am asking this specifically from Web API perspective. Is there a series of MUST Log this or MUST trace this.
Like, INFO traces about a controller's request, any NULL checks, etc.
Is there a reference list that can be validated against to ensure optimum logging and tracing coverage in ASP.NET Web API ?
So I will assume your goal for the logging is, as it should be, to debug the application rather than measure for performance.
While I think there is no one 'right' answer to this, at the minimum I would always try to log
Timestamps, class/function names and thread name (if yr running a multithreaded app) in every log line
Quick log line # every entry point, along with the full contents of
the passed in request, preferably in a format that would make it
easier for you to reissue the same request from fiddler or a similar
tool (this can be done via a custom action filter - see how the
author uses these for performance monitoring a web api app here )
If you are doing any database queries as part of your action, log
the full query sql string if possible (once again to make it easier
to repeat during debugging) as well as at least the # of rows
returned
If you are doing any external service calls, log both the full
request and response strings
Use try/catch blocks to log any exceptions (you can also use
something like the ELMAH library to do this automatically rather
than handling in code - link here and here
Anything that is resolved during runtime - think values from config files, database queries, calculated values, should also be logged
I'm sure there is more missing from this list - after all this varies on what yr doing in the app. You should be asking yourself at every step of the way - what could go wrong in my application? What things would I or the poor chap that will work on this after me find useful whilst debugging a problem?
If you are hosting your webapi in IIS, you can enable IIS LOG and counters:
http://www.iis.net/configreference/system.applicationhost/sites/site/logfile
Performance Counters:
http://msdn.microsoft.com/en-us/library/fxk122b4%28v=VS.100%29.aspx
http://www.iis.net/learn/extensions/configuring-application-request-routing-(arr)/using-performance-counters
An additional category of items to log for a service code that implements authorization authentication and impersonation where elevated access is required. These should be configurable to log either success failure or both.
I have an un-ideal application and without going into the ins and outs this is what is needed.
A 3rd party app needs to make a request to a page which will return data. Because I have Forms Authentication enabled this request always ends up being sent to the login page. I have therefore set it so that all users can see this page even though they are not logged in. What I want to do in the Page Load or similar is to check querystring parameters which the 3rd party app can send and validate it against FormsAuthentication.
When this 3rd party app makes its request a user has already logged on so I was wondering is it possible that I can check something against the currently logged in user to see if it matches the 3rd party request?
What I need to also do is send that information from the logged in user to the 3rd party app so that when it makes its request it matches up with the logged in user.
I may get down votes for this, but I'm going to answer anyway because if one of my co-workers asked me this question, I would read them the riot act. (I won't read you the riot act because I'm not responsible for your systems or the security of your data.)
I see from your first sentence that you realize this may not be the best idea because it is an "un-ideal" application.
I know that what I'm about to suggest will result in duplicate code and add to maintenance down the road, but when you balance that against short-circuiting the authentication mechanism or tampering with a well-known and trustworthy mechanism to weaken it so as to allow another application to use a "back door" (which is what you're really talking about doing here - creating a back door for this other application but attempting to use querystring parameters as part of the login mechanism) it is really the lesser of two evils to have more code and more to maintain.
So... Have you considered, and is it a possibility for you to set up another method for this other app to get the data? You say that it is just getting data, so why not have a separate web services project or some other project appropriate. Even another web site application would be a better solution to what you're proposing.
Even if this data is not what you would call "Sensitive" I still think trying to build in a back door is a bad idea. It may not be a critical issue on the current application, but not coding for security is a habit, and once you do it in one area, you're more likely to take unnecessary risks elsewhere.