Where is the dictionary key "MS_HttpContext" defined for HttpRequestMessage.Properties? - c#

I've searched everywhere and nowhere does it mention where this key is defined, or similar ones such as HTTP_X_FORWARDED_FOR, REMOTE_ADDR etc.
MSDN documentation doesn't mention anything useful. The only thing close to useful I came about was some stackoverflow questions (this and this), along with this short blog post.
None of these sadly address my current question - from where does all these dictionary keys come from? Where is their specification, so that one knows they exist and learn to utilize them, by seeing the contents they hold?
EDIT: I'm using .NET Framework 4.6.0, where System.Net.Http's version is 4.0.0.0.
To get the client IP, I'm doing the following:
public string GetSomeIp(HttpRequestMessage request)
{
HttpContextWrapper context =
request.Properties["MS_HttpContext"] as HttpContextWrapper;
return (context == null) ?
string.Empty : (context.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]
?? context.Request.ServerVariables["REMOTE_ADDR"]).Split(',')[0].Trim();
}
I'd like to find the documentation, which explains what MS_HttpContext does/holds in detail, as well as REMOTE_ADDR, HTTP_X_FORWADED_FOR, and where they are defined, so I can see all the other keys and more in detail of their implementation/proper usage.
I'm aware of the following server variables, but the keys used here are not mentioned there. (except REMOTE_ADDR)

I'd like to find the documentation, which explains what MS_HttpContext does/holds in detail
The System.Web.Http.* assemblies seem not described on the https://referencesource.microsoft.com/.
However, all these projects are now hosted on the GitHub as Open? Source https://github.com/aspnet/AspNetWebStack.
So far, I assume that this constant/key is used within a routine that assigns the System.Web -> HttpContext to System.Web.Http -> Request.
https://github.com/aspnet/AspNetWebStack/blob/master/src/System.Web.Http.WebHost/HttpRequestMessageExtensions.cs#L11-L44
Another occurrences are related to CORS and Tests. You can clone this repo and search for the "MS_HttpContext" occurrences in depth in you are looking for details. However, I am not sure about its documentation.
where this key is defined, or similar ones such as HTTP_X_FORWARDED_FOR, REMOTE_ADDR etc.
from where does all these dictionary keys come from?
These request's properties (aka Server Variables) are created (almost duplicated) from the corresponding headers sent by a client here (applicable for HttpContext - ASP.NET WebForms/MVC):
https://referencesource.microsoft.com/#System.Web/HttpRequest.cs,dc76880a3cfd0009
https://referencesource.microsoft.com/#System.Web/HttpRequest.cs,639
By the way, there are no more such properties in the HttpRequest for ASP.NET Core (headers only).
If you need to grab the client IP information, use any approach from the aforementioned (yours or suggested) links.
If you need to retrieve the familiar HttpContext instance (for example, outside the ApiController, for example, DelegatingHandler/aka middleware), use any of the approaches illustrated in this (already mentioned as well).
If you need to retrieve it inside the ApiController, it may be even easier (don't forget about required null ref checks and self-hosted WebAPI solutions):
public class YourApiController : ApiController {
public HttpResponseMessage YourActionName() {
var request = new HttpContextWrapper(CurrentContext).Request;
...
}
}
public class YourAuditHandler : DelegatingHandler {
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
string ipAddress = HttpContext.Current != null ? HttpContext.Current.Request.UserHostAddress : "0.0.0.0";
...
}
}

Related

QnAmaker change default answer when QnAmaker does not have any response

How to change default answer when QnAmaker does not have any response to display a prompt dialog.
For example:
User1: Hello
Bot : Hello there !!
User1: Do you sell cars?
Bot : No good match found !
Instead of No good match found, the bot should propose a list of services available.
Also, anytime a match is not found, the bot should again propose a list of services available.
How can this be achieve?
QnAMakerAttribute has a defaultMessage parameter allowing you to customize the 'no match' response text: https://github.com/Microsoft/BotBuilder-CognitiveServices/blob/7866f5a1bc970bdd0be341b9ba24c74067edf57c/CSharp/Library/QnAMaker/QnAMaker/QnAMakerService/QnAMakerAttribute.cs
public class BasicQnAMakerDialog : QnAMakerDialog
{
public BasicQnAMakerDialog() : base(
new QnAMakerService(
new QnAMakerAttribute(
Utils.GetAppSetting("QnASubscriptionKey"),
Utils.GetAppSetting("QnAKnowledgebaseId"),
"**List of services: one, two three**",
0.30,
8))) {}
}
There is also a pull request waiting to be merged that will allow overriding sending the default message: https://github.com/Microsoft/BotBuilder-CognitiveServices/pull/87 Until then, it seems your only option is to duplicate the QnAMakerDialog in your own code base: QnAMakerDialog source
Because there's a few different ways to use the QnA maker alongside the botframework there's quite a few differing suggestions for the issue you have at the moment but not as many proper guidelines from Microsoft around it at this time. (At least not that I've found)
I came across this issue listed against the QnA makers git repository: found here. There are a few different suggestions, so I'll list them below from least to most effort.
Option 1: [Assumes you're creating a base dialog class that connects to the QnA maker]
public BasicQnAMakerDialog() : base(new QnAMakerService(new QnAMakerAttribute(ConfigurationManager.AppSettings["QnASubscriptionKey"], ConfigurationManager.AppSettings["QnAKnowledgebaseId"], "No good match in FAQ")))
Option 2: [Simply look out for the specific string that's returned by default and 'override' it]
protected override async Task RespondFromQnAMakerResultAsync(IDialogContext context, IMessageActivity message, QnAMakerResults result)
{
var answer = result.Answers.First().Answer;
Activity reply = ((Activity)context.Activity).CreateReply();
if (reply.Text.equals("Not Match Found!))
reply.Text = "No good match in FAQ";
await context.PostAsync(reply);
}
There were instances back when QnAMaker was still in it's preview that option 1 wouldn't work as expected. Option 2 is not as neat in my opinion but it's a decent work around.
As Eric has said in his answer, there is an active pull request awaiting a merge against this issue in their git repo. So eventually this will be an easier thing to deal with. Until then hopefully the above two options will help.

Retrieving HttpContext in a Custom NLog Target

I may me missing something basic here - but is it possible to retrieve the HttpContext.Current in a custom NLog event?
I am trying to give each request a unique Guid so that I can correlate logging messages to a single event (i.e, tie together each log event for a single request). So, I want to store this Guid in HttpContext.Current.Items, then retrieve it in the NLog target and include it in the log message.
Here is my example target where I'd like to access HttpContext.Current:
[Target("AzureTableTarget")]
public class AzureTableTarget : TargetWithLayout
{
public AzureTableTarget()
{
_appSettings = IoCResolver.Get<IAppSettings>();
}
protected override void Write(LogEventInfo logEvent)
{
var correlationId = HttpContext.Current; //This is always null
var batchOperation = new TableBatchOperation();
CxLogEventBuilder.Build(_appSettings, logEvent).ForEach(batchOperation.Insert);
_loggingTable.ExecuteBatchAsync(batchOperation);
}
}
Nowadays it's easier to retrieve the HTTP Context in a NLog target (works for ASP.NET and ASP.NET Core)
Install NLog.Web (ASP.NET) or NLog.Web.AspNetCore (ASP.NET Core) package
For ASP.NET core, follow the ASP.NET Core - NLog setup
Inherit from AspNetLayoutRendererBase (namespace NLog.Web.LayoutRenderers)
Get the request by calling var context = HttpContextAccessor.HttpContext;
Example:
[LayoutRenderer("aspnet-sessionid")]
[ThreadSafe]
public class AspNetSessionIdLayoutRenderer : AspNetLayoutRendererBase
{
protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent)
{
var context = HttpContextAccessor.HttpContext;
var contextSession = context?.Session();
if (contextSession == null)
{
InternalLogger.Debug("HttpContext Session Lookup returned null");
return;
}
builder.Append(contextSession.SessionID); // ASP.NET Core: contextSession.Id
}
}
PS: there are currently many predefined renderers for ASP.NET (Core): https://nlog-project.org/config/?tab=layout-renderers&search=aspnet
If your custom target should capture one (or more) context-specific values, then I recommend that your target inherits from TargetWithContext (or AsyncTaskTarget).
It gives the ability to setup and capture contextproperty-items. Where the Layout can be assigned to capture context-details. Examples of possible context-details easily available from HttpContext:
https://nlog-project.org/config/?tab=layout-renderers&search=package:nlog.web.aspnetcore
For more details about writing custom-targets:
https://github.com/NLog/NLog/wiki/How-to-write-a-custom-target-for-structured-logging
https://github.com/NLog/NLog/wiki/How-to-write-a-custom-async-target
Btw. there already exists this custom target that nicely inherits from AsyncTaskTarget:
https://www.nuget.org/packages/NLog.Extensions.AzureCosmosTable/
This article about Working with HttpContext.Current might help. The key, for you, might be that when control passes from one thread to another HttpContext.Current in the new thread can be null.
Here is another question/answer from here on SO that describes HttpContext.Current being null in the context of a web service. The accepted answer suggests turning on ASP.Net compatibility in your web.config file.
I don't know of either of these will help, but they might. I found them by googling for "HttpContext.Current is null", which yielded quite a number of hits. I have done very little ASP.NET development, so I can't really comment on HttpContext.Current from my own personal experience.
Given your use case, I would suggest that you look into System.Diagnostics.CorrelationManager.ActivityId.
One nice feature of ActivityId is that it is "flowed" from parent threads to child threads (including thread pool threads). I think that it works well with Tasks and Parallel operations. Works well meaning that the ActivityId, as set in a parent thread, has the expected value in a child thread.
There is not a LayoutRenderer for ActivityId, but it easy enough to write one. See an example (written against NLog 1.0) here:
Most useful NLog configurations
I'm pretty sure that the "EstimatedBufferSize" stuff is no longer needed, so something like will probably work:
[LayoutRenderer("ActivityId")]
class ActivityIdLayoutRenderer : LayoutRenderer
{
protected override void Append(StringBuilder builder, LogEventInfo logEvent)
{
builder.Append(Trace.CorrelationManager.ActivityId);
}
}
If you go this route, you might consider adding a Format property to the ActivityIdLayoutRenderer to allow you to specify the guid format. See this answer (from me). It contains a lot of useful information about working with guids.
NewGuid vs System.Guid.NewGuid().ToString("D");
See this source file (in NLog's git repository) for an example of how you can implement and use such a Format property:
https://github.com/NLog/NLog/blob/master/src/NLog/LayoutRenderers/GuidLayoutRenderer.cs

How to use Delta<T> from Microsoft ASP.NET Web API OData with Code First\JsonMediaTypeFormatter

What is the issue?
I am trying to enable patching in my ASP.net web api app. I'm using code first entity framework.
I have the following method header which I can set a breakpoint in and it will hit:
[AcceptVerbs("PATCH")]
public async Task<HttpResponseMessage> Patch(long appId, long id, Delta<SimpleFormGroup> formGroup)
However when I call formGroup.Patch(entity), no changes are made to my entity. If I put the following into the immediate window:
formGroup.GetChangedPropertyNames()
Then this collection is empty, which seems wrong.
What have I tried?
I have been referring to the following examples
http://techbrij.com/http-patch-request-asp-net-webapi
http://www.strathweb.com/2013/01/easy-asp-net-web-api-resource-updates-with-delta/
It seems to be a problem with the Json MediaType Formatter not knowing how to build the Delta object correctly, however in the 2nd link filip does seem to suggest that it should work without the oDataMediaTypeFormatter.
I have started down the line of trying to serialise my model to EDMX representation, then from there extract the CSDL so I can create an oDataMediaTypeFormatter, but I have hit a snag there too, plus it seems a bit overkill.
If anyone could shed any light on this it'd be much appreciated. Let me know if any more information is needed.
EDIT:
Here is the class definition for SimpleFormGroup:
public class SimpleFormGroup
{
public int LastUpdate;
public string Identifier;
public string Title;
public int DisplayOrder;
}
And here is the data that I am sending:
Content-Type: 'application/json'
{ "DisplayOrder" : "20 }
Interesting, it looks like Delta<T> with int members doesn't work in JSON.
Unfortunately, Delta<T> was created specifically for OData. If Delta<T> appears to be working with any formatter other than OData, it's a coincidence rather than being intentional.
The good news though is that there's nothing stopping you from defining your own PATCH format for JSON, and I'd be surprised if no one has already written one that works better with Json.NET. It's possible that we'll revisit patching in a future release of Web API and try to come up with a consistent story that works across formatters.
Thanks to Youssef for investigating and discovering why things weren't working. Hopefully that can get solved down the line.
I managed to crack this myself in the end after poring over the oData package source. I chose to implement another MediaTypeFormatter that wraps up the logic as it provides easy access tio HttpContent, but there are other ways to achieve this.
The key part was figuring out how to interpret the code first model, see the commented line below:
public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
var builder = new ODataConventionModelBuilder();
// This line will allow you to interpret all the metadata from your code first model
builder.EntitySet<EfContext>("EfContext");
var model = builder.GetEdmModel();
var odataFormatters = ODataMediaTypeFormatters.Create(model);
var delta = content.ReadAsAsync(type, odataFormatters).Result;
var tcs = new TaskCompletionSource<object>();
tcs.SetResult(delta);
return tcs.Task;
}
Hope this saves someone some trouble!

How can I get the URL of the current page from within a C# App_Code class?

I have a logging class that, well, logs things. I would like to add the ability to automatically have the current page be logged with the messages.
Is there a way to get the information I'm looking for?
Thanks,
From your class you can use the HttpContext.Current property (in System.Web.dll). From there, you can create a chain of properties:
Request
Url and RawUrl
The underlying object is a Page object, so if you cast it to that, then use any object you would normally use from within a Page object, such as the Request property.
It's brittle and hard to test but you can use System.Web.HttpContext.Current which will give you a Request property which in turn has the RawUrl property.
public static class MyClass
{
public static string GetURL()
{
HttpRequest request = HttpContext.Current.Request;
string url = request.Url.ToString();
return url;
}
}
I tried to break it down a little :)
In the past I've also rolled my own logging classes and used Console.Writeln() but really there are a number of good logging options that already exist so why go there? I use NLog pretty much everywhere; it is extremely flexible with various log output destinations including console and file, lots of log format options, and is trivial to set up with versions targeting the various .net frameworks including compact. Running the installer will add NLog config file options to the Visual Studio Add New Item dialog. Using in your code is simple:
// declare in your class
private static Logger logger = LogManager.GetCurrentClassLogger();
...
// use in your code
logger.Debug(() => string.Format("Url: {0}", HttpContext.Current.Request.Url));

OAuth in C# as a client

I've been given 6 bits of information to access some data from a website:
Website Json Url (eg: http://somesite.com/items/list.json)
OAuth Authorization Url (eg: http://somesite.com/oauth/authorization)
OAuth Request Url (eg: http://somesite.com/oauth/request)
OAuth Access Url (eg: http://somesite.com/oauth/access)
Client Key (eg: 12345678)
Client Secret (eg: abcdefghijklmnop)
Now, I've looked at DotNetOpenAuth and OAuth.NET libraries, and while I'm sure they are very capable of doing what I need, I just can't figure out how to use either in this way.
Could someone post some sample code of how to consume the Url (Point 1.) in either library (or any other way that may work just as well)?
Thanks!
I also just started working with OAuth a month ago and was also confused by all these libraries. One thing I realized about these libraries is that they're quite complicated (as you have found out). Another thing that makes it hard is that there wasn't a lot of example (it was worse in my case because I was trying to implement a Provider and not a Client).
Originally, I wanted to use the latest OAuth 2.0 but the only .NET library out there that implements it is DotNetOpenAuth. It's probably one of the most complete .NET OAuth library out there but it'll take too long for me to understand (due to not knowing WCF, MVC, etc). I have since downgraded to OAuth 1.0a because I found these examples for DevDefined OAuth. I don't know about you but I found it easier to learn from examples.
It looks like you only want to implement a Client so make sure to look at the Consumer examples. Try to compile the examples and ignore the Provider examples because you don't need them and it'll make you more confused. Be patient. If you're still confused, it might be a good idea to look at some of the libraries made for other languages as they might have easier to understand documentations.
OK, I know your last post was months ago, but in case you were still working on this (or for people like me who would have loved to see an answer to this question), here's some information regarding the NullReferenceException you encountered creating the OAuth request:
The null reference comes from the IServiceLocator that is used to resolve dependencies. If you don't explicitly pass one into the constructor, it uses the static property ServiceLocator.Current in the Microsoft.Practices.ServiceLocation namespace.
This is one of the many pitfalls of using static methods and global state, is you hide issues like this from the consumer of your API. So if you haven't specified a default service locator, then null is returned, resulting in the NullReferenceException.
So to fix this issue, I wired up an implementation of IServiceLocator that uses StructureMap (one of the many IoC containers available) as the container. Lastly, you will need to register instances for two interfaces: ISigningProvider and INonceProvider. Luckily, several standard implementations exist in the OAuth.Net.Components assembly, such as GuidNonceProvider and HmacSha1SigningProvider.
The resulting code looks like something like this:
var container = new Container();
container.Configure(a => a.For<INonceProvider>().Use<GuidNonceProvider>());
container.Configure(a => a.For<ISigningProvider>()
.Use<HmacSha1SigningProvider>()
.Named("signing.provider:HMAC-SHA1"));
var locator = new StructureMapAdapter(container);
ServiceLocator.SetLocatorProvider(delegate { return locator; });
I realize this isn't the final solution to your original question (I'm still working on getting it working myself), but I hope it gets you a few steps further. And if you've long abandoned this implementation altogether... well, happy coding anyway!
For OAuth 2.0:
I learned that it's easiest to just put up the authentication page in an HTML window then trap the returned access_token. You can then do that using in client-side web browser.
For example, in MonoTouch it would be:
//
// Present the authentication page to the user
//
var authUrl = "http://www.example.com/authenticate";
_borwser.LoadRequest (new NSUrlRequest (new NSUrl (authUrl)));
//
// The user logged in an we have gotten an access_token
//
void Success(string access_token) {
_web.RemoveFromSuperview();
var url = "http://www.example.com/data?access_token=" + access_token;
// FETCH the URL as needed
}
//
// Watch for the login
//
class Del : UIWebViewDelegate
{
public override void LoadingFinished (UIWebView webView)
{
try {
var url = webView.Request.Url.AbsoluteString;
var ci = url.LastIndexOf ("access_token=");
if (ci > 0) {
var code = url.Substring (ci + "access_token=".Length);
_ui.Success (code);
}
} catch (Exception error) {
Log.Error (error);
}
}
}

Categories