How do I access Telemetry Headers in Service Fabric Controller? - http-headers

I am able to examine Request Headers at my Service Fabric Controller entry point by specifying the following method signature:
public async Task<IActionResult> Copy([FromHeader] TelemetryHeaders headers)
where TelemetryHeaders is defined as:
public class TelemetryHeaders
{
// the following properties are my guesses as to what the headers might be named
[FromHeader]
[JsonProperty(PropertyName = "OperationId")]
public string OperationId {get; set;}
[FromHeader]
[JsonProperty(PropertyName = "ParentId ")]
public string ParentId {get; set;}
// the following properties are defined by the W3C standard for telemetry headers
[FromHeader]
[JsonProperty(PropertyName = "parent-id")]
public string W3C_ParentId {get; set;}
[FromHeader]
[JsonProperty(PropertyName = "trace-id")]
public string W3C_TraceId {get; set;}
// the following properties are defined by the HTTP Request standard for telemetry headers
[FromHeader]
[JsonProperty(PropertyName = "Request-Id")]
public string HTTP_RequestId {get; set;}
// the following properties are defined in
// Microsoft.ApplicationInsights.ServiceFabric/RequestResponseHeaders.cs and/or
// Microsoft.ApplicationInsights.AspNetCore/DiagnosticListeners/RequestResponseHeaders.cs
[FromHeader]
[JsonProperty(PropertyName = "Request-Context")]
public string RequestContextHeader {get; set;}
[FromHeader]
[JsonProperty(PropertyName = "appId")]
public string RequestContextCorrelationSourceKey {get; set;}
[FromHeader]
[JsonProperty(PropertyName = "appId")]
public string RequestContextCorrelationTargetKey {get; set;}
[FromHeader]
[JsonProperty(PropertyName = "roleName")]
public string RequestContextSourceRoleNameKey {get; set;}
[FromHeader]
[JsonProperty(PropertyName = "Microsoft.ApplicationInsights.ServiceFabric.ParentId")]
public string ParentIdHeaderName {get; set;}
[FromHeader]
[JsonProperty(PropertyName = "Microsoft.ApplicationInsights.ServiceFabric.CorrelationContext")]
public string CorrelationContextHeaderName {get; set;}
[FromHeader]
[JsonProperty(PropertyName = "appId")]
public string RequestContextSourceKey {get; set;}
[FromHeader]
[JsonProperty(PropertyName = "appId")]
public string RequestContextTargetKey {get; set;}
[FromHeader]
[JsonProperty(PropertyName = "Request-Id")]
public string RequestIdHeader {get; set;}
[FromHeader]
[JsonProperty(PropertyName = "Correlation-Context")]
public string CorrelationContextHeader {get; set;}
[FromHeader]
[JsonProperty(PropertyName = "traceparent")]
public string TraceParentHeader {get; set;}
[FromHeader]
[JsonProperty(PropertyName = "tracestate")]
public string TraceStateHeader {get; set;}
}
In addition, my Startup.cs contains the following configuration code.
var appInsightsConnection = this.Configuration["ClientGatewayOptions:ClientGateway_AppInsightsConnection"];
var options = new ApplicationInsightsServiceOptions
{
ConnectionString = appInsightsConnection,
EnablePerformanceCounterCollectionModule = true,
EnableRequestTrackingTelemetryModule = true,
EnableEventCounterCollectionModule = true,
EnableDependencyTrackingTelemetryModule = true,
EnableAppServicesHeartbeatTelemetryModule = true,
EnableAzureInstanceMetadataTelemetryModule = true,
EnableQuickPulseMetricStream = true,
EnableAdaptiveSampling = true,
EnableHeartbeat = true,
AddAutoCollectedMetricExtractor = true,
EnableDiagnosticsTelemetryModule = true,
};
options.RequestCollectionOptions.InjectResponseHeaders = true;
options.RequestCollectionOptions.TrackExceptions = true;
services.AddApplicationInsightsTelemetry(options);
I generate my request using Postman and specify values for OperationId and ParentId. When I hit a breakpoint at the top of the controller, I see the values I explicitly set in my Postman script, but I do not see any headers that I expect the Azure Service Fabric infrastructure to set.
In addition,
var currentActivity = Activity.Current;
which works fine in Azure Functions, is always null in Service Fabric.
And finally,
var context = _telemetryClient.Context;
while context is not null, all of its values are either empty or null.
So, how do I access the telemetry headers I'm looking for?
Thanks for your assistance.

Related

Mapping nested x-form-urlencoded data to DTO in Asp.NET Core

Implementing a webhook in Asp.Net Core which is POSTed to with application/x-form-urlencoded data - it's receiving data in a format that is designed to be easily processable in PHP w/ the $_POST variable (nested associative array) - the form fields look like
foo
bar[barf]
baz[bat][bark]
baz[bat][bant]
Is there a nice (elegant and little code required) way to wire up the Asp.NET Core model binding to handle the nested structure here? i.e. when the webhook gets POSTed to, we parse a C# POCO -
something like
class RootDto {
public string Foo {get; set;}
public Bar Bar {get; set;}
public Baz Baz {get; set;}
public class Bar {
public string Barf {get; set;}
}
public class Baz {
public Bat Bat {get; set;}
public class Bat {
public string Bark {get; set;}
public string Bant {get; set;}
}
}
}
The POST body looks something like the following:
foo=somevalue&bar%5Bbarf%5D=anothervalue&baz%5Bbat%5D%5Bbark%5D=123.0&baz%5Bbat%5D%5Bbant%5D=5000
i.e.
foo=somevalue&bar[barf]=anothervalue&baz[bat][bark]=123.0&baz[bat][bant]=5000
Also, what's the low-friction way to set up a type-converter for one of these fields (e.g. assume the field "Foo" comes in as a string but we want to parse it into a struct)?
Note that I don't have control of the shape or encoding of the data coming in from the webhook (e.g. I can't request they just send me JSON).
Request body
Content-Type: application/x-www-form-urlencoded
foo=somevalue&bar%5Bbarf%5D=anothervalue&baz%5Bbat%5D%5Bbark%5D=123.0&baz%5Bbat%5D%5Bbant%5D=5000
It just works.... I have plain .net core project and controller looks like
public IActionResult Post([FromForm] RootDto request)
{
return Ok(request);
}
Btw your root class seems to be wrong I've changed to make it work
public class RootDto {
public string Foo {get; set;}
public BarClass Bar {get; set;}
public BazClass Baz {get; set;}
public class BarClass {
public string Barf {get; set;}
}
public class BazClass {
public BatClass Bat {get; set;}
public class BatClass {
public string Bark {get; set;}
public string Bant {get; set;}
}
}
}

Serializing data using XmlArrayItemAttribute not working well

I have this DataContract, which is an array of strings:
[System.Xml.Serialization.XmlArrayAttribute(Order = 19)]
[System.Xml.Serialization.XmlArrayItemAttribute("CardNumber", typeof(string), IsNullable = false)]
[DataMember]
public string[] Cards {get; set; }
As I read, it should be serialized like this:
<Cards>
<CardNumber>123123</CardNumber>
</Cards>
but I'm still getting:
<Cards>
<string>123123</string>
</Cards>
What's wrong with it?
You can use CollectionDataContract instead.
First, create a class:
[CollectionDataContract(ItemName="CardNumber")]
public class CardsList : List<string> { }
And then, replace this line:
[DataMember]
public string[] Cards {get; set; }
By this:
[DataMember(Name="Cards")]
public CardsList Cards {get; set; };
Hope it helps.

Trouble formulating inner joins using NHibernate Linq query

Using NHibernate 3.3.1.400, I'm having problems expressing what is a simple SQL statment using NHibernate's Linq provider.
My domain model looks like this:
public class Site
{
public virtual Guid Id {get; set;}
public virtual string Name {get; set;}
}
// a site has many filers
public class Filer
{
public virtual Guid Id {get set;}
public virtual Site Site {get; set;}
public virtual string Name {get; set;}
}
// a filer has many filings
public class Filing
{
public virtual Guid Id {get set;}
public virtual Filer Filer {get; set;}
public virtual DateTime FilingDate {get; set;}
}
//a filing has many items
public class Item
{
public virtual Guid Id {get set;}
public virtual Filing Filing {get; set;}
public virtual DateTime Date {get; set;}
public virtual decimal Amount {get; set;}
}
public class SearchName
{
public virtual Guid Id {get set;}
public virtual string Name {get; set;}
}
// there are potentially many NameLink objects tied to a single search name
public abstract class NameLink
{
public virtual Guid Id {get set;}
public virtual SearchName SearchName {get; set;}
}
public class NameLinkToFiler: NameLink
{
public virtual Filer Filer {get; set;}
}
public class NameLinkToItem: NameLink
{
public virtual Item Item {get; set;}
}
My query is supposed to return a list of matching Item elements:
var query = session.Query<Item>()
.Where(x => x.Filing.Filer.Site == mySite);
The joins connecting Site -> Filer -> Filing -> Item are working great through my mappings, but the problems start when I try to join the NameLinkToFiler or NameLinkToItem classes based on user input.
If the user wants to filter the Query results with a filer name, I want to join the results of the Item query with the results of this query:
var filerNameQuery = session.Query<NameLinkToFiler>()
.Where(q=>q.SearchName.Contains('some name'));
I want the results of the NameLinkToFiler.Filer property to join the Item.Filing.Filer property, so my list of returned items is reduced.
Note: The 'Contains' keyword above is a full-text index search I'm using as described here. It's working fine, and let's just assume the filerNameQuery is an IQueryable<NameLinkToFiler>.
It's pretty easy to do this in straight SQL:
select filer.Name, filing.FilingDate, filer.Name, item.Date, item.Amount
from Search_Name searchNameForFiler, Search_Name searchNameForItem, Name_Link_Filer nameLinkFiler,
Name_Link_Item nameLinkItem, Item item, Filing filing, Filer filer, Site s
where
contains(searchNameForFiler.Name, :filerName) and searchNameForFiler.Id = nameLinkFiler.SearchNameId and nameLinkFiler.FilerId = filer.Id and
contains(searchNameForItem.Name, :itemName) and searchNameForItem.Id = nameLinkItem.SearchNameId and nameLinkItem.ItemId = item.Id
and item.FilingId = filing.Id
and filing.FilerId = filer.Id
and filing.SiteId = :site
...but I don't want to lose the compile-time checks for this sort of query.
Thanks.
Apparently, the answer is to not use lambda syntax.
This works fine:
query = from t in parentItemQuery
join l in Session.Query<NameLinkToFiler>() on t.Filing.Filer.Id equals l.Filer.Id
join n in Session.Query<SearchName>() on l.SearchName.Id equals n.Id
where sn.Contains(request.FilerName)
select t;

Castle Active Record - Nested Data Column Prefix

I have a few classes structured similar to those shown below.
[ActiveRecord]
public class Request : ActiveRecordBase
{
[PrimaryKey]
public int Id {get; set;}
[Nested("SectionA")]
public SectionA A {get; set;}
[Nested("SectionB")]
public SectionB B {get; set;}
}
public class SectionA
{
[Property]
public string Description {get; set;}
[Property]
public string Remark {get; set;}
[HasMany(typeof(Attachment),
Table="Attachments", ColumnKey="RequestId",
Where="Section = 'SectionA'")]
public IList Attachments {get; set;}
}
public class SectionB
{
[Property]
public string Description {get; set;}
[HasMany(typeof(Attachment),
Table="Attachments", ColumnKey="RequestId",
Where="Section = 'SectionB'")]
public IList Attachments {get; set;}
}
[ActiveRecord]
public class Attachment
{
[PrimaryKey]
public int Id {get; set;}
[BelongsTo("RequestId")]
public Request Owner {get; set;}
[Property]
public string Section {get; set;}
[Property]
public string FilePath {get; set;}
}
Everything works fine, except that the columns for Attachment Class will have the prefix as well. And it happens quite randomly, as in some time it does have the prefix and sometime it doesn't.
Is there any way to prevent the Attachment from having the prefix, or is there a better way to structure my classes that prevent this issues.
Seems like way is prevent the nested prefix on Attachment class is to connect Request & Attachment directly. Still need to observe for a few iteration.
[ActiveRecord]
public class Request : ActiveRecordBase
{
[PrimaryKey]
public int Id {get; set;}
[HasMany(typeof(Attachment)]
public IList Attachments {get; set;}
[Nested("SectionA")]
public SectionA A {get; set;}
[Nested("SectionB")]
public SectionB B {get; set;}
}

NHibernate Criteria

public class A
{
public string aname {get; set;}
public string aId {get; set;}
public string bId {get; set;}
}
public class B
{
public string bId {get; set;}
public string bname {get; set;}
public string cId {get; set;}
}
public class C
{
public string cId {get; set;}
public string cfirstname {get; set;}
public string clastname {get; set;}
}
public class abcDTO
{
public string aname {get; set;}
public string bname {get; set;}
public string clastname {get; set;}
}
Evetually the query which I am looking is
SELECT a.aid, b.bname, c.clastname FROM A thisa
inner join B thisb on thisa.bid=thisb.bid
inner join C thisc on thisb.cid=thisc.cid and this_.POLICY_SEARCH_NBR like '%-996654%'
The criteria which I am trying is, Please let me know the best possible way to write a criteria so that I can get the abcdto object as result
var policyInsuranceBusiness = DetachedCriteria.For<A>()
.SetProjection(Projections.Property("a.aid"))
.Add(Restrictions.Like("a.aid", "1-SAP-3-996654", MatchMode.Anywhere))
.CreateCriteria("b.bid", "b", JoinType.InnerJoin)
.SetProjection(Projections.Property("b.bname")) // ERROR OUT - COULD NOT RESOLVE PROPERTY
.CreateCriteria("c.cid", "c", JoinType.InnerJoin)
.SetProjection(Projections.Property("c.clastname")); // ERROR - COULD NOT RESOLVE PROPERTY
IList<abcDTO> plo = policyInsuranceBusiness.GetExecutableCriteria(_session).SetResultTransformer(NHibernate.Transform.Transformers
.AliasToBean<abcDTO).List<abcDTO>();
You can't join objects in NHibernate without having a relationship between them defined in the classes and in the mappings.
So taking your example I would estimate the following class definitions:
public class A {
public virtual string Name {get; set;}
public virtual string PolicySearchNumber {get; set;}
public virtual int Id {get; set;}
public virtual B B {get; set;}
}
public class B {
public virtual int Id {get; set;}
public virtual string Name {get; set;}
public virtual C C {get; set;}
}
public class C {
public virtual int Id {get; set;}
public virtual string Firstname {get; set;}
public virtual string Lastname {get; set;}
}
public class abcDTO {
public string int aid {get; set;}
public string aname {get; set;}
public string bname {get; set;}
public string clastname {get; set;}
}
And your Criteria Query would be:
var results = session.CreateCriteria<A>()
.CreateCriteria("B", "b")
.CreateCriteria("b.C", "c")
.SetProjection(Projections.ProjectionList()
.Add(Projections.Property("Id"), "aid")
.Add(Projections.Property("Name"), "aname")
.Add(Projections.Property("b.Name"), "bname")
.Add(Projections.Property("c.Lastname"), "clastname")
)
.SetResultTransformer(new AliasToBeanResultTransformer(typeof(abcDTO)))
.List<abcDTO>();
You can optionally choose Inner or Left Joins depending on how you handle null references in the Criteria Query.