DownstreamContext of context not found - ocelot

I'm trying to add a custom middleware to add parameters to the query.
According to some online search, you can do something like this:
{
//PreQueryStringBuilderMiddleware occurs after authorization
PreQueryStringBuilderMiddleware = async (ctx, next) =>
{
var upstreamRoute = ctx.DownstreamReRoute.UpstreamPathTemplate;
Log.Information($"{upstreamRoute}");
await next.Invoke();
}
};
See this answer
But for me it says HttpContext doesn't contain a definition of DownstreamReRoute.
Is there something I am missing or has this been changed?

Alright, turned out this did actually change and in an earlier versions this still works. But it looks like Ocelot is dead anyway from what I read.

var upstreamRoute = ctx.Items.DownstreamRoute().UpstreamPathTemplate
Use above code instead of
var upstreamRoute = ctx.DownstreamReRoute.UpstreamPathTemplate;
Such change was done between 15.0.6 and 16.0.0 Ocelot versions.
For details you can check them on github: https://github.com/ThreeMammals/Ocelot/compare/15.0.6...16.0.0

Related

after await next when I try to use serilog LogContext it doesn’t push any property to log messages

While setting everything for Serilog and SEQ I was stuck in an issue that you may have an answer for it.
I am trying to add some properties to all logs using LogContext.PushProperty. However, in my middleware(see image below) the LogContext can push property to logs before await next.Invoke(). While after await next when I try to use LogContext it doesn’t push any property to log messages.
The issue is that claims are always empty before the await next.Invoke() and they only have values after await next so I am forced to use LogContext after the await but it doesn’t work there as mentioned. Please advise if you have a clue?
Thanks,
LogContext needs to be used in conjunction with a using block, covering the whole scope in which you want the property to be available. You may need something like:
IDisposable popContext = null;
var user2 = context.User as IAMClaimsUser;
if (user2 != null && !string.IsNullOrEmpty(user2.FirstName))
{
popContext = LogContext.PushProperty("UserEmail", user2.Email);
}
using (popContext)
{
// `UserEmail` will be attached to events logged in this block
await next();
}

How to redirect Filters in ASP.NET CORE 3.1

I have an attribute class that extends IAsyncActionFilter in ASP.NET CORE 3.1 (C#). Inside the OnActionExecutionAsync method, I would like to redirect to another controller/method WITHOUT calling any other filters that are on the initial method call.
I have tried using this inside OnActionExecutionAsync :
context.Result = new RedirectToActionResult("MethodName", "Home", null);
await next();
I get the following error when I do that:
If an IAsyncActionFilter provides a result value by setting the Result
property of ActionExecutingContext to a non-null value, then it cannot
call the next filter by invoking ActionExecutionDelegate.
I can remove the await next(), but then other filters on the initial method being called get called.
I have searched Google extensively, but come up short.
What is the proper syntax to achieve this goal?
Thanks!
I faced with the same problem and since no one answered, I just share my solution.
Just don't call next() if you set Result:
context.Result = new RedirectToActionResult("MethodName", "Home", null);
if (context.Result != null)
await next();

How to get route values for any url in asp.net core?

I need to get the route values for an arbitrary URL in ASP.NET MVC Core.
It could be something like this SO question: How to determine if an arbitrary URL matches a defined route, because I haven't found any direct way to do it.
And I haven't been able to do it with that approach either.
It looks like once I have an HttpContext with a Request for the url, it's easy to get the route values, and looking at the source code for aspnet/Hosting in GitHub I got to the point where HttpContextFactory gets created, but that was it, just couldn't go any further!
Does someone know how to do this?
Thanks in advance!
I know this an older post, but this is what I did in order to get RouteData from a RouteCollection running in an ASP.NET MVC Core app based on a URL.
public async Task<ActionResult> GetRouteDataForUrl([FromQuery(Name = "url")] string url)
{
var uri = new Uri(url);
var httpContext = new DefaultHttpContext();
httpContext.Request.Path = uri.PathAndQuery;
var routeContext = new RouteContext(httpContext);
var router = RouteData.Routers.First(); //get the top level router
await router.RouteAsync(routeContext); //router updates routeContext
return new JsonResult(routeContext.RouteData.Values);
}
The routeContext.RouteData is populated by the root level router.
Ref: Net6
You can install the package and use the namespace
using Microsoft.AspNetCore.Routing;
then you can get route values like this
var routeData = _httpContextAccessor.HttpContext.GetRouteData(); ;
var namedRouteValue = _httpContextAccessor.HttpContext.GetRouteValue("route-key");
Try please;
var t = ViewContext.RouteData.Values["id"];

Cloud Function retrieving a value based on URL parameter

I am trying to write a Cloud Function in node where I can return a token from a parameter.
The URL I use is...
https://us-central1-nmnm03.cloudfunctions.net/GetAccount?taccount=Asd
my function is this... and its wrong. I suspect I am not assigning TT properly.
var functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.GetAccount = functions.https.onRequest((req, res) => {
const t = admin.database().ref('/newaccout/'+req.query.account)
const tt = t.child(token)
res.send( "res is " + tt );
});
req.query.account is the Key. One of the Items in the document is token
ideally, I would like to get something like...
{"token":"23453458885"}
Could I get a node hint please... thanks
Though, I am not a firebase geek. What it seems from the documentation is that you will have two events that you can use to listen for retrieving child data. You can read further more here. The given options are used for different cases. Please follow through the mentioned link to have clear view.
Inside your cloud function you can try doing following:
const t = admin.database().ref('/newaccout/'+req.query.account)
t.on('child_added', function(data) {
res.json({
token: data.token
})
})
Or maybe like this:
const t = admin.database().ref('/newaccout/'+req.query.account)
t.once('value', function(snapshot) {
//Process it like above
//But here you will get al child elements at once
});
It looks like you are expecting to query the value found at a database reference stored at t. Unfortunately, you haven't actually performed a query yet. tt is just yet another Reference object that points to a location in the database. You should use the once() method on Reference to query a database location. Also bear in mind that you are using a variable called token, but you haven't defined yet in your code. To me, that looks like it would generate an error to me.
You might be well served by looking at a bunch of the sample code.

Is it possible to `bind` a handlebars helper before render? (using express & hbs)

I've got a helper called feature that looks like this:
hbs.registerHelper('feature', function(request, flag, options) {
if (features(flag, request)) {
return options.fn(this);
} else if (options.inverse) {
return options.inverse(this);
}
});
And used in the template over and over like this:
{{feature request "some-feature"}} ... {{/feature}}
I'd love to be able to remove the request part in the template as it's always the same value and never changes. So I imagine I could bind request to feature when it's rendered, and obviously that changes each time and I don't want it spilling out to other request.
Something like:
res.render("page", {
feature: hbs.helper.feature.bind(null, req)
});
Is this possible?
If you are not using known helpers mode then the helper evaluation will check the context so you can pass in a bind like you have above and it should work.
Under the latest code in handlebars master the eval is something like:
helper = helpers.foo || (depth0 && depth0.foo) || helperMissing
helper.call(depth0, 1, {"name":"foo","hash":{},"data":data}
Where depth0 is the current context object. The caveat here is that helpers are given priority so you need to name them differently. You should also be able to do something like {{./foo bar}} to give priority to the local context's version but it appears that we have a bug where that isn't honored under this particular syntax construct.