<?xml version="1.0" encoding="UTF-8" standalone="no"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:georss="http://www.georss.org/georss" xmlns:media="http://search.yahoo.com/mrss/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" version="2.0">

<channel>
	<title>Brian Pedersen's Sitecore and .NET Blog</title>
	<atom:link href="https://briancaos.wordpress.com/feed/" rel="self" type="application/rss+xml"/>
	<link>https://briancaos.wordpress.com</link>
	<description>Sitecore, C#, ASP.NET, ASP.NET Core for developers</description>
	<lastBuildDate>Tue, 09 Jun 2026 07:36:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<site xmlns="com-wordpress:feed-additions:1">4258391</site><cloud domain="briancaos.wordpress.com" path="/?rsscloud=notify" port="80" protocol="http-post" registerProcedure=""/>
<image>
		<url>https://s2.wp.com/i/webclip.png</url>
		<title>Brian Pedersen's Sitecore and .NET Blog</title>
		<link>https://briancaos.wordpress.com</link>
	</image>
	<atom:link href="https://briancaos.wordpress.com/osd.xml" rel="search" title="Brian Pedersen's Sitecore and .NET Blog" type="application/opensearchdescription+xml"/>
	<atom:link href="https://briancaos.wordpress.com/?pushpress=hub" rel="hub"/>
	<xhtml:meta content="noindex" name="robots" xmlns:xhtml="http://www.w3.org/1999/xhtml"/><item>
		<title>C# Convert GeoJSON FeatureCollection to SqlGeography for SQL Server</title>
		<link>https://briancaos.wordpress.com/2026/06/09/c-convert-geojson-featurecollection-to-sqlgeography-for-sql-server/</link>
					<comments>https://briancaos.wordpress.com/2026/06/09/c-convert-geojson-featurecollection-to-sqlgeography-for-sql-server/#respond</comments>
		
		<dc:creator><![CDATA[briancaos]]></dc:creator>
		<pubDate>Tue, 09 Jun 2026 07:36:16 +0000</pubDate>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[.NET Core]]></category>
		<category><![CDATA[General .NET]]></category>
		<category><![CDATA[FeatureCollection]]></category>
		<category><![CDATA[Geography]]></category>
		<category><![CDATA[GeoJson]]></category>
		<category><![CDATA[Geometry]]></category>
		<category><![CDATA[MultiPolygon]]></category>
		<category><![CDATA[Polygon]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">http://briancaos.wordpress.com/?p=4097</guid>

					<description><![CDATA[When working with geographic data in .NET, you often receive geographic shapes as GeoJSON – the standard format used by tools like geojson.io and MapTiler. To store and query this data in Microsoft SQL Server, you need to convert it &#8230; <a href="https://briancaos.wordpress.com/2026/06/09/c-convert-geojson-featurecollection-to-sqlgeography-for-sql-server/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">When working with geographic data in .NET, you often receive geographic shapes as <a href="https://geojson.org/">GeoJSON</a> – the standard format used by tools like <a href="https://geojson.io/">geojson.io</a> and <a href="https://www.maptiler.com/">MapTiler</a>. To store and query this data in Microsoft SQL Server, you need to convert it to the <code>SqlGeography</code> type from the <a href="https://www.nuget.org/packages/Microsoft.SqlServer.Types">Microsoft.SqlServer.Types</a> NuGet package. The code is available on <a href="https://github.com/briancaos/SqlGeographyService">GitHub</a>.</p>



<h2 class="wp-block-heading">The GeoJSON FeatureCollection</h2>



<p class="wp-block-paragraph">GeoJSON uses a <code>FeatureCollection</code> as the root object. It contains an array of <code>Feature</code> objects, each with a <code>geometry</code> (the shape) and a <code>properties</code> bag (any metadata you want to attach).</p>



<p class="wp-block-paragraph">A typical GeoJSON file looks like this:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; first-line: 1; title: ; notranslate">
{
  "type": "FeatureCollection",
  "features": &#91;
    {
      "type": "Feature",
      "geometry": {
        "type": "Polygon",
        "coordinates": &#91;
          &#91;
            &#91;10.0, 55.0],
            &#91;12.0, 55.0],
            &#91;12.0, 57.0],
            &#91;10.0, 57.0],
            &#91;10.0, 55.0]
          ]
        ]
      },
      "properties": {
        "name": "My Region"
      }
    }
  ]
}
</pre></div>


<p class="wp-block-paragraph">The C# model that maps directly to this structure uses <code>System.Text.Json</code>. The <code>Coordinates</code> property is kept as a raw <code>JsonElement</code> because the coordinate structure differs between geometry types (<code>Polygon</code> vs <code>MultiPolygon</code>):</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; first-line: 1; title: ; notranslate">
using System.Text.Json;
using System.Text.Json.Serialization;

public class FeatureCollection
{
  &#91;JsonPropertyName(&quot;type&quot;)]
  public string? Type { get; set; }

  &#91;JsonPropertyName(&quot;features&quot;)]
  public List&lt;Feature&gt;? Features { get; set; }
}

public class Feature
{
  &#91;JsonPropertyName(&quot;type&quot;)]
  public string? Type { get; set; }

  &#91;JsonPropertyName(&quot;geometry&quot;)]
  public FeatureGeometry? Geometry { get; set; }

  &#91;JsonPropertyName(&quot;properties&quot;)]
  public JsonElement? Properties { get; set; }
}

public class FeatureGeometry
{
  &#91;JsonPropertyName(&quot;type&quot;)]
  public string? Type { get; set; }

  // MultiPolygon: double&#91;polygon]&#91;ring]&#91;point]&#91;coordinate]
  // Polygon: double&#91;ring]&#91;point]&#91;coordinate]
  &#91;JsonPropertyName(&quot;coordinates&quot;)]
  public JsonElement? Coordinates { get; set; }
}
</pre></div>


<h2 class="wp-block-heading">Deserializing a GeoJSON file</h2>



<p class="wp-block-paragraph">Use <code>JsonSerializer.DeserializeAsync</code> to load a <code>.geojson</code> file into the model:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; first-line: 1; title: ; notranslate">
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };

await using var stream = File.OpenRead(&quot;regions.geojson&quot;);
var collection = await JsonSerializer.DeserializeAsync&lt;FeatureCollection&gt;(stream, options);
</pre></div>


<h2 class="wp-block-heading">Converting FeatureGeometry to SqlGeography</h2>



<p class="wp-block-paragraph">The <code>SqlGeographyService</code> class converts a <code>FeatureGeometry</code> to a <code>SqlGeography</code> using SRID 4326 (WGS84). It supports <code>Polygon</code> and <code>MultiPolygon</code> types. Coordinates are rounded to 5 decimal places. If the resulting geometry is invalid, <code>MakeValid()</code> is called automatically.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; first-line: 1; title: ; notranslate">
using Microsoft.SqlServer.Types;
using System.Text.Json;

public class SqlGeographyService
{
  public static SqlGeography ToSqlGeography(FeatureGeometry geometry)
  {
    if (!geometry.Coordinates.HasValue)
      throw new ArgumentException(&quot;Geometry coordinates cannot be null.&quot;);

    SqlGeography sqlGeography;
    switch (geometry.Type)
    {
      case &quot;Polygon&quot;:
        var polygon = geometry.Coordinates.Value.Deserialize&lt;List&lt;List&lt;double&#91;]&gt;&gt;&gt;();
        sqlGeography = BuildPolygon(polygon ?? new List&lt;List&lt;double&#91;]&gt;&gt;());
        break;
      case &quot;MultiPolygon&quot;:
        var multiPolygon = geometry.Coordinates.Value.Deserialize&lt;List&lt;List&lt;List&lt;double&#91;]&gt;&gt;&gt;&gt;();
        sqlGeography = BuildMultiPolygon(multiPolygon ?? new List&lt;List&lt;List&lt;double&#91;]&gt;&gt;&gt;());
        break;
      default:
        throw new NotSupportedException($&quot;Geometry type &#039;{geometry.Type}&#039; is not supported.&quot;);
    }

    if (!sqlGeography.STIsValid())
    {
      sqlGeography = sqlGeography.MakeValid();
    }
    return sqlGeography;
  }

  public static SqlGeography BuildPolygon(List&lt;List&lt;double&#91;]&gt;&gt; coordinates)
  {
    var builder = new SqlGeographyBuilder();
    builder.SetSrid(4326);
    builder.BeginGeography(OpenGisGeographyType.Polygon);

    foreach (var ring in coordinates)
    {
      if (ring == null || ring.Count &lt; 4)
        continue;

      bool first = true;
      foreach (var coord in ring)
      {
        double lon = Math.Round(coord&#91;0], 5);
        double lat = Math.Round(coord&#91;1], 5);

        if (first) { builder.BeginFigure(lat, lon); first = false; }
        else { builder.AddLine(lat, lon); }
      }
      builder.EndFigure();
    }
    builder.EndGeography();
    return builder.ConstructedGeography;
  }

  public static SqlGeography BuildMultiPolygon(List&lt;List&lt;List&lt;double&#91;]&gt;&gt;&gt; coordinates)
  {
    var builder = new SqlGeographyBuilder();
    builder.SetSrid(4326);
    builder.BeginGeography(OpenGisGeographyType.MultiPolygon);

    foreach (var polygon in coordinates)
    {
      builder.BeginGeography(OpenGisGeographyType.Polygon);
      foreach (var ring in polygon)
      {
        if (ring == null || ring.Count &lt; 4)
          continue;

        bool first = true;
        foreach (var coord in ring)
        {
          double lon = Math.Round(coord&#91;0], 5);
          double lat = Math.Round(coord&#91;1], 5);

          if (first) { builder.BeginFigure(lat, lon); first = false; }
          else { builder.AddLine(lat, lon); }
        }
        builder.EndFigure();
      }
      builder.EndGeography();
    }
    builder.EndGeography();
    return builder.ConstructedGeography;
  }
}
</pre></div>


<h2 class="wp-block-heading">Inserting into SQL Server</h2>



<p class="wp-block-paragraph">Given a table with a <code>geography</code> column:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; first-line: 1; title: ; notranslate">
CREATE TABLE Regions (
    Id    INT PRIMARY KEY,
    Name  NVARCHAR(200),
    Shape geography
);
</pre></div>


<p class="wp-block-paragraph">Loop through the <code>FeatureCollection</code>, convert each geometry and insert it:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; first-line: 1; title: ; notranslate">
foreach (var feature in collection?.Features ?? &#91;])
{
    if (feature.Geometry == null) continue;

    SqlGeography shape = SqlGeographyService.ToSqlGeography(feature.Geometry);

    using var cmd = new SqlCommand(
        "INSERT INTO Regions (Id, Name, Shape) VALUES (@Id, @Name, @Shape)", connection);

    cmd.Parameters.AddWithValue("@Id", id++);
    cmd.Parameters.AddWithValue("@Name",
        feature.Properties?.TryGetProperty("name", out var n) == true ? n.GetString() : "");

    var param = cmd.Parameters.Add("@Shape", System.Data.SqlDbType.Udt);
    param.UdtTypeName = "geography";
    param.Value = shape;

    await cmd.ExecuteNonQueryAsync();
}
</pre></div>


<p class="wp-block-paragraph">The full source code, including the <code>FeatureCollection</code> and <code>SqlGeographyService</code> classes, is available on <a href="https://github.com/briancaos/SqlGeographyService">GitHub</a>.</p>



<p class="wp-block-paragraph"><strong>MORE TO READ:</strong></p>



<ul class="wp-block-list">
<li><a href="https://briancaos.wordpress.com/2025/06/17/c-cosmosdb-spatial-geographic-search-using-geojson-coordinates/">C# CosmosDB spatial geographic search using GeoJSON coordinates</a> by briancaos</li>



<li><a href="https://geojson.org/">GeoJSON specification (RFC 7946)</a> from geojson.org</li>



<li><a href="https://geojson.io/">geojson.io – online GeoJSON viewer and editor</a> from geojson.io</li>



<li><a href="https://learn.microsoft.com/en-us/sql/relational-databases/spatial/spatial-data-sql-server">Spatial Data in SQL Server</a> from Microsoft Learn</li>



<li><a href="https://www.nuget.org/packages/Microsoft.SqlServer.Types">Microsoft.SqlServer.Types NuGet package</a> from nuget.org</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://briancaos.wordpress.com/2026/06/09/c-convert-geojson-featurecollection-to-sqlgeography-for-sql-server/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4097</post-id>
		<media:content medium="image" url="https://2.gravatar.com/avatar/b1cd26d13baf270ccbc554e8071367bfe693798598bb33f3784394cfde1e1537?s=96&amp;d=https%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96">
			<media:title type="html">briancaos</media:title>
		</media:content>
	</item>
		<item>
		<title>Azure Functions in Isolated Mode and Application Insights</title>
		<link>https://briancaos.wordpress.com/2026/02/10/azure-functions-in-isolated-mode-and-application-insights/</link>
					<comments>https://briancaos.wordpress.com/2026/02/10/azure-functions-in-isolated-mode-and-application-insights/#respond</comments>
		
		<dc:creator><![CDATA[briancaos]]></dc:creator>
		<pubDate>Tue, 10 Feb 2026 09:23:10 +0000</pubDate>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[.NET Core]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[General .NET]]></category>
		<category><![CDATA[Microsoft Azure]]></category>
		<category><![CDATA[ai]]></category>
		<category><![CDATA[Application Insights]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[Azure Functions]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Filter]]></category>
		<category><![CDATA[ILogger]]></category>
		<category><![CDATA[Isolated]]></category>
		<category><![CDATA[microsoft]]></category>
		<category><![CDATA[technology]]></category>
		<guid isPermaLink="false">http://briancaos.wordpress.com/?p=4087</guid>

					<description><![CDATA[As per current (2026-02-10) there seem to be an issue where Application Insights cannot read loglevels from the host.json file. So If you wish to filter messages from System.Net.Http.HttpClient for example, any setting in the host.json file is ignored: You &#8230; <a href="https://briancaos.wordpress.com/2026/02/10/azure-functions-in-isolated-mode-and-application-insights/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">As per current (2026-02-10) there seem to be an issue where Application Insights cannot read loglevels from the host.json file. So If you wish to filter messages from System.Net.Http.HttpClient for example, any setting in the host.json file is ignored:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; highlight: [11,12,13,14,15,16,17,18,19,20,21,22]; title: ; notranslate">
{
  "version": "2.0",
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request"
      },
      "enableDependencyTracking": false
    },
    "logLevel": {
      "Default": "Information",
      "Host.Results": "Warning",
      "Host.Aggregator": "Error",
      "Microsoft": "Warning",
      "System": "Warning",
      "System.Net.Http.HttpClient": "Error",
      "Microsoft.AspNetCore": "Warning",
      "Azure.Core": "Warning",
      "Azure.Storage": "Warning",
      "Azure": "Warning"
    }
  }
}
</pre></div>


<p class="wp-block-paragraph">You need to hardcode the settings into your program.cs file instead. Here is a program.cs template that can be used when creating Azure Functions running in isolated mode:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication()
    .ConfigureServices((context, services) =&gt;
    {
      // Setup proper logging levels for Application Insights 
      services.AddApplicationInsightsTelemetryWorkerService();
      services.ConfigureFunctionsApplicationInsights();
      services.Configure&lt;LoggerFilterOptions&gt;(options =&gt;
      {
        // Add specific rules for Application Insights provider
        // Needed, as Application Insights ignore the host.json logging configuration 
        var defaultRule = options.Rules.FirstOrDefault(rule =&gt;
              rule.ProviderName == &quot;Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider&quot;);
        if (defaultRule is not null)
        {
          options.Rules.Remove(defaultRule);
        }

        options.Rules.Add(new LoggerFilterRule(
              &quot;Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider&quot;,
              &quot;Microsoft&quot;,
              LogLevel.Warning,
              null));

        options.Rules.Add(new LoggerFilterRule(
              &quot;Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider&quot;,
              &quot;System&quot;,
              LogLevel.Warning,
              null));

        options.Rules.Add(new LoggerFilterRule(
              &quot;Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider&quot;,
              &quot;Azure&quot;,
              LogLevel.Warning,
              null));

        options.Rules.Add(new LoggerFilterRule(
              &quot;Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider&quot;,
              &quot;Host.Results&quot;,
              LogLevel.Warning,
              null));

        options.Rules.Add(new LoggerFilterRule(
              &quot;Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider&quot;,
              &quot;Host.Aggregator&quot;,
              LogLevel.Error,
              null));

        // Default namespace at Information level for Application Insights
        // This allows you to write logger.LogInformation in your code and have it
        // show up in Application Insights, while still filtering out less
        // important logs from the framework and Azure SDKs
        options.Rules.Add(new LoggerFilterRule(
              &quot;Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider&quot;,
              &quot;Default&quot;,
              LogLevel.Information,
              null));

        options.Rules.Add(new LoggerFilterRule(
              &quot;Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider&quot;,
              null,
              LogLevel.Information,
              null));
      });

      // Add your Dependency Injection registrations here   
      // Add your Dependency Injection registrations here   
      // Add your Dependency Injection registrations here   

    })
    .ConfigureLogging((context, logging) =&gt;
    {
      // Apply logging configuration from host.json - to be used locally
      // and for non-Application Insights providers
      logging.AddConfiguration(context.Configuration.GetSection(&quot;logging&quot;));
      logging.AddApplicationInsights();
    })
    .Build();

await host.RunAsync();
</pre></div>


<p class="wp-block-paragraph">With this setup, you can have a host.json file with log levels set for your console logs when testing locally, and a more fine grained setup when logging to application insights.</p>



<p class="wp-block-paragraph"><strong>MORE TO READ:</strong></p>



<ul class="wp-block-list">
<li><a href="https://briancaos.wordpress.com/2022/06/10/c-log-to-application-insights-and-file-from-your-net-6-application/" target="_blank" rel="noreferrer noopener">C# Log to Application Insights and File from your .NET 6 Application</a> by briancaos</li>



<li><a href="https://briancaos.wordpress.com/2020/11/17/filtering-application-insights-telemetry-using-a-itelemetryprocessor/" target="_blank" rel="noreferrer noopener">Filtering Application Insights telemetry using a ITelemetryProcessor</a> by briancaos</li>



<li><a href="https://briancaos.wordpress.com/2020/02/19/application-insights-not-working-in-net-core-console-application-remember-to-flush-the-telemetryclient/">Application Insights not working in .NET Core Console Application – Remember to flush the TelemetryClient</a> by briancaos</li>



<li><a href="https://medium.com/@iamprovidence/step-by-step-guide-to-logs-in-c-best-practices-and-tips-491c8d555d26" target="_blank" rel="noreferrer noopener">Step-by-Step Guide to Logs in C#: Best Practices and Tips</a> by iamprovidence</li>



<li><a href="https://mattfrear.com/2024/08/22/logging-to-application-insights-with-ilogger-in-azure-functions-on-net-8/" target="_blank" rel="noreferrer noopener">Logging to Application Insights with ILogger in Azure functions on .NET 8</a> by mattfrear</li>



<li><a href="https://learn.microsoft.com/en-us/azure/azure-functions/dotnet-isolated-process-guide?tabs=ihostapplicationbuilder%2Ccode%2Cwindows#managing-log-levels" target="_blank" rel="noreferrer noopener">Guide for running C# Azure Functions in the isolated worker model</a> from microsoft</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://briancaos.wordpress.com/2026/02/10/azure-functions-in-isolated-mode-and-application-insights/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4087</post-id>
		<media:content medium="image" url="https://2.gravatar.com/avatar/b1cd26d13baf270ccbc554e8071367bfe693798598bb33f3784394cfde1e1537?s=96&amp;d=https%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96">
			<media:title type="html">briancaos</media:title>
		</media:content>
	</item>
		<item>
		<title>C# Azure Functions in .NET Isolated Mode does not read host.json file</title>
		<link>https://briancaos.wordpress.com/2026/01/05/c-azure-functions-in-net-isolated-mode-does-not-read-host-json-file/</link>
					<comments>https://briancaos.wordpress.com/2026/01/05/c-azure-functions-in-net-isolated-mode-does-not-read-host-json-file/#respond</comments>
		
		<dc:creator><![CDATA[briancaos]]></dc:creator>
		<pubDate>Mon, 05 Jan 2026 13:25:56 +0000</pubDate>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[.NET Core]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[General .NET]]></category>
		<category><![CDATA[Microsoft Azure]]></category>
		<category><![CDATA[Application Insights]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[Azure Function]]></category>
		<category><![CDATA[Azure Functions]]></category>
		<category><![CDATA[host.json]]></category>
		<category><![CDATA[Log]]></category>
		<guid isPermaLink="false">http://briancaos.wordpress.com/?p=4074</guid>

					<description><![CDATA[So it turns out that all of my grieves with Azure Functions and logging to Application Insights are based around the fact that the settings from host.json is not being read, because the host.json file is ignored by Azure Functions &#8230; <a href="https://briancaos.wordpress.com/2026/01/05/c-azure-functions-in-net-isolated-mode-does-not-read-host-json-file/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">So it turns out that all of my grieves with <a href="https://briancaos.wordpress.com/tag/azure-functions/" target="_blank" rel="noreferrer noopener">Azure Functions</a> and logging to <a href="https://learn.microsoft.com/en-us/azure/azure-monitor/visualize/insights-overview" target="_blank" rel="noreferrer noopener">Application Insights</a> are based around the fact that the settings from <a href="https://learn.microsoft.com/en-us/azure/azure-functions/dotnet-isolated-process-guide?tabs=ihostapplicationbuilder%2Ccode%2Cwindows" target="_blank" rel="noreferrer noopener">host.json</a> is not being read, because the host.json file is ignored by <a href="https://learn.microsoft.com/en-us/azure/azure-functions/dotnet-isolated-process-guide?tabs=ihostapplicationbuilder%2Ccode%2Cwindows" target="_blank" rel="noreferrer noopener">Azure Functions running in .NET Isolated mode</a>. </p>



<p class="wp-block-paragraph">So that&#8217;s why all of the logging settings in host.json does not matter:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
{
  "version": "2.0",
  "Logging": {
    "ApplicationInsights": {
      "EnableLiveMetricsFilters": true,
      "SamplingSettings": {
        "IsEnabled": true,
        "ExcludedTypes": "Request"
      },
      "EnableDependencyTracking": false,
      "LogLevel": {
        "Default": "Information",
        "Function": "Warning",
        "System.Net.Http.HttpClient": "None",
      }
    },
    "LogLevel": {
      "Default": "Information",
      "Function": "Information",
      "System.Net.Http.HttpClient": "None",
    }
  }
}
</pre></div>


<p class="wp-block-paragraph">The file above should enable me to ignore logs from the System.Net.Http.HttpClient namespace, but still allow information level logs that I make myself:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
_logger.LogInformation("This should end up in application insights");
</pre></div>


<p class="wp-block-paragraph">To enable the host.json file, you need to add it manually in your Program.cs:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
var builder = FunctionsApplication.CreateBuilder(args);

// Add the host.json file
builder.Configuration.AddJsonFile("host.json", optional: true, reloadOnChange: false);

builder.Services.AddApplicationInsightsTelemetryWorkerService().ConfigureFunctionsApplicationInsights();
builder.Logging.AddApplicationInsights();

...
...
</pre></div>


<p class="wp-block-paragraph">Now you can configure the log levels to be logged in Application Insights.</p>



<p class="wp-block-paragraph"><strong>MORE TO READ:</strong></p>



<ul class="wp-block-list">
<li><a href="https://github.com/Azure/azure-functions-core-tools/issues/3059" target="_blank" rel="noreferrer noopener">Azure Functions &#8211; Disable this log &#8211; &#8220;Sending HTTP request GET https//&#8230;.&#8221;</a> from Github</li>



<li><a href="https://briancaos.wordpress.com/2020/11/17/filtering-application-insights-telemetry-using-a-itelemetryprocessor/" target="_blank" rel="noreferrer noopener">Filtering Application Insights telemetry using a ITelemetryProcessor</a> from briancaos</li>



<li><a href="https://briancaos.wordpress.com/2022/06/10/c-log-to-application-insights-and-file-from-your-net-6-application/" target="_blank" rel="noreferrer noopener">C# Log to Application Insights and File from your .NET 6&nbsp;Application</a> from briancaos</li>



<li><a href="https://learn.microsoft.com/en-us/answers/questions/1294469/how-to-stop-azure-functions-from-logging-request-h" target="_blank" rel="noreferrer noopener">How to stop Azure functions from logging request headers to log stream?</a> from Microsoft Learn</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://briancaos.wordpress.com/2026/01/05/c-azure-functions-in-net-isolated-mode-does-not-read-host-json-file/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4074</post-id>
		<media:content medium="image" url="https://2.gravatar.com/avatar/b1cd26d13baf270ccbc554e8071367bfe693798598bb33f3784394cfde1e1537?s=96&amp;d=https%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96">
			<media:title type="html">briancaos</media:title>
		</media:content>
	</item>
		<item>
		<title>C# CosmosDB spatial geographic search using GeoJSON coordinates</title>
		<link>https://briancaos.wordpress.com/2025/06/17/c-cosmosdb-spatial-geographic-search-using-geojson-coordinates/</link>
					<comments>https://briancaos.wordpress.com/2025/06/17/c-cosmosdb-spatial-geographic-search-using-geojson-coordinates/#comments</comments>
		
		<dc:creator><![CDATA[briancaos]]></dc:creator>
		<pubDate>Tue, 17 Jun 2025 08:09:20 +0000</pubDate>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[.NET Core]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[General .NET]]></category>
		<category><![CDATA[Microsoft Azure]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[CosmosDB]]></category>
		<category><![CDATA[Geographic]]></category>
		<category><![CDATA[Geolocation]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[Spatial]]></category>
		<guid isPermaLink="false">http://briancaos.wordpress.com/?p=4051</guid>

					<description><![CDATA[If you have data in an Azure CosmosDB, it is possible to perform spatial location based searches, returning documents within a distance from a point, or within a certain area. The first thing you need, is to store the longitude &#8230; <a href="https://briancaos.wordpress.com/2025/06/17/c-cosmosdb-spatial-geographic-search-using-geojson-coordinates/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">If you have data in an <a href="https://azure.microsoft.com/en-us/products/cosmos-db" target="_blank" rel="noreferrer noopener">Azure CosmosDB</a>, it is possible to perform spatial location based searches, returning documents within a distance from a point, or within a certain area.</p>



<p class="wp-block-paragraph">The first thing you need, is to store the longitude and latitude in a <a href="https://doc.arcgis.com/en/arcgis-online/reference/geojson.htm" target="_blank" rel="noreferrer noopener">GeoJSON</a> object. Having the coordinates in ordinary fields will not allow you to do a geographic search.</p>



<p class="wp-block-paragraph">The GeoJSON object have the following format:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
{
    "type": "Point",
    "coordinates": &#91;
        &lt;longitude&gt;,
        &lt;latitude&gt;
    ]
}
</pre></div>


<p class="wp-block-paragraph">A correctly formatted object in CosmosDB look like this:</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><a href="https://briancaos.wordpress.com/wp-content/uploads/2025/06/cosmosdbgeojson.png"><img width="1024" height="653" data-attachment-id="4056" data-permalink="https://briancaos.wordpress.com/2025/06/17/c-cosmosdb-spatial-geographic-search-using-geojson-coordinates/cosmosdbgeojson/" data-orig-file="https://briancaos.wordpress.com/wp-content/uploads/2025/06/cosmosdbgeojson.png" data-orig-size="1479,944" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="CosmosDBGeoJson" data-image-description="" data-image-caption="" data-large-file="https://briancaos.wordpress.com/wp-content/uploads/2025/06/cosmosdbgeojson.png?w=640" src="https://briancaos.wordpress.com/wp-content/uploads/2025/06/cosmosdbgeojson.png?w=1024" alt="GeoJSON object in CosmosDB" class="wp-image-4056" srcset="https://briancaos.wordpress.com/wp-content/uploads/2025/06/cosmosdbgeojson.png?w=1024 1024w, https://briancaos.wordpress.com/wp-content/uploads/2025/06/cosmosdbgeojson.png?w=150 150w, https://briancaos.wordpress.com/wp-content/uploads/2025/06/cosmosdbgeojson.png?w=300 300w, https://briancaos.wordpress.com/wp-content/uploads/2025/06/cosmosdbgeojson.png?w=768 768w, https://briancaos.wordpress.com/wp-content/uploads/2025/06/cosmosdbgeojson.png?w=1440 1440w, https://briancaos.wordpress.com/wp-content/uploads/2025/06/cosmosdbgeojson.png 1479w" sizes="(max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">GeoJSON object in CosmosDB</figcaption></figure>
</div>


<p class="wp-block-paragraph">With that data, you can perform a location based search. </p>



<p class="wp-block-paragraph"><strong>PREREQUISITES: ENSURE THE INDEXING POLICY INCLUDE SPATIAL INDEXING</strong></p>



<p class="wp-block-paragraph">If your spatial queries does not work, check that <a href="https://docs.azure.cn/en-us/cosmos-db/index-policy" target="_blank" rel="noreferrer noopener">spatial indexing</a> is enabled.</p>



<p class="wp-block-paragraph">In the &#8220;Settings&#8221; for your container, check that the Indexing Policy include your location GeoJSON as a spatial point. My field is called &#8220;location&#8221;, yours can be named differently:</p>



<figure class="wp-block-image size-large"><a href="https://briancaos.wordpress.com/wp-content/uploads/2025/06/cosmosdbspatialindexing.png"><img width="1024" height="565" data-attachment-id="4062" data-permalink="https://briancaos.wordpress.com/2025/06/17/c-cosmosdb-spatial-geographic-search-using-geojson-coordinates/cosmosdbspatialindexing/" data-orig-file="https://briancaos.wordpress.com/wp-content/uploads/2025/06/cosmosdbspatialindexing.png" data-orig-size="1488,822" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="CosmosDBSpatialIndexing" data-image-description="" data-image-caption="" data-large-file="https://briancaos.wordpress.com/wp-content/uploads/2025/06/cosmosdbspatialindexing.png?w=640" src="https://briancaos.wordpress.com/wp-content/uploads/2025/06/cosmosdbspatialindexing.png?w=1024" alt="Spatial Indexing Enabled" class="wp-image-4062" srcset="https://briancaos.wordpress.com/wp-content/uploads/2025/06/cosmosdbspatialindexing.png?w=1024 1024w, https://briancaos.wordpress.com/wp-content/uploads/2025/06/cosmosdbspatialindexing.png?w=150 150w, https://briancaos.wordpress.com/wp-content/uploads/2025/06/cosmosdbspatialindexing.png?w=300 300w, https://briancaos.wordpress.com/wp-content/uploads/2025/06/cosmosdbspatialindexing.png?w=768 768w, https://briancaos.wordpress.com/wp-content/uploads/2025/06/cosmosdbspatialindexing.png?w=1440 1440w, https://briancaos.wordpress.com/wp-content/uploads/2025/06/cosmosdbspatialindexing.png 1488w" sizes="(max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">Spatial Indexing Enabled</figcaption></figure>



<p class="wp-block-paragraph"><strong>STEP 1: CREATE A MODEL FOR THE COSMOSDB DOCUMENT</strong></p>



<p class="wp-block-paragraph">This is not specific for the CosmosDB location search, but generally, you need to map the JSON document in CosmosDB to a C# model. This is a simplified version of mine. Yours will look different.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; highlight: [13,16,20,24]; title: ; notranslate">
using Newtonsoft.Json;
using System.Text.Json.Serialization;

namespace MyCode
{
  public class BeautifulWorldModel
  {
    &#91;JsonPropertyName("panoId")]
    public string PanoId { get; set; }

    &#91;JsonProperty("location")]
    &#91;JsonPropertyName("location")]
    public Location Location { get; set; }
  }

  public class Location
  {
    &#91;JsonProperty("type")]
    &#91;JsonPropertyName("type")]
    public string? Type { get; set; }

    &#91;JsonProperty("coordinates")]
    &#91;JsonPropertyName("coordinates")]
    public double&#91;] Coordinates { get; set; }
  }
}
</pre></div>


<p class="wp-block-paragraph"><em><strong>NOTE</strong>: Both System.Text.Json and NewtonSoft.Json is required for CosmosDB operations in C#. The <a href="https://www.nuget.org/packages/microsoft.azure.cosmos/" target="_blank" rel="noreferrer noopener">Microsoft.Azure.Cosmos</a> NuGet package is dependent on NewtonSoft.Json (as per 2025-06-17). This will change in the future. </em></p>



<p class="wp-block-paragraph"><strong>STEP 2: PERFORM THE COSMOSDB LOCATION SEARCH</strong></p>



<p class="wp-block-paragraph">The geobased search is straight forward, as you query CosmosDB like any other query. Granularity is in meters. The search look like this:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
SELECT * FROM c
WHERE ST_DISTANCE(c.location, {
  &quot;type&quot;: &quot;Point&quot;,
  &quot;coordinates&quot;: &#91;12.5757, 55.6796]
}) &lt; 100
</pre></div>


<p class="wp-block-paragraph">This search returns any document with a location within 100 meters from the provided coordinates.</p>



<p class="wp-block-paragraph">An example repository look like this:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
using Microsoft.Azure.Cosmos;

namespace MyCode
{
  public class BeautifulWorldRepository
  {
    private Container _container;

    public BeautifulWorldRepository()
    {
      CosmosClient cosmosClient = new CosmosClient(&quot;YOUR_COSMOSDB_URL&quot;, &quot;YOUR_COSMOSDB_KEY&quot;);
      _container = cosmosClient.GetContainer(
        &quot;YOUR_COSMOSDB_DATABASE&quot;, 
        &quot;YOUR_COSMOSDB_CONTAINER&quot;);
    }

    public async Task&lt;IEnumerable&lt;BeautifulWorldModel&gt;&gt; GetByLocationAsync(double longitude, double latitude, int distanceInMeters)
    {
      var query = new QueryDefinition(&quot;SELECT * FROM c WHERE ST_DISTANCE(c.location, {\&quot;type\&quot;: \&quot;Point\&quot;, \&quot;coordinates\&quot;: &#91;@longitude, @latitude]}) &lt; @distance&quot;)
        .WithParameter(&quot;@longitude&quot;, longitude)
        .WithParameter(&quot;@latitude&quot;, latitude)
        .WithParameter(&quot;@distance&quot;, distanceInMeters);
      FeedIterator&lt;BeautifulWorldModel&gt; resultSet = _container.GetItemQueryIterator&lt;BeautifulWorldModel&gt;(query);
      List&lt;BeautifulWorldModel&gt; results = new List&lt;BeautifulWorldModel&gt;();
      while (resultSet.HasMoreResults)
      {
        foreach (var item in await resultSet.ReadNextAsync())
        {
          results.Add(item);
        }
      }
      return results;
    }
  }
}
</pre></div>


<p class="wp-block-paragraph"><strong>PERFORM LOCATION SEARCH WITHIN A RECTANGLE</strong></p>



<p class="wp-block-paragraph">The search query for searching within a rectangle is slightly more complex. You must add 5 points to your rectangle, and you must add them COUNTER CLOCKWISE. Adding them clockwise will return all locations.</p>



<p class="wp-block-paragraph">You add the 4 corners of the rectangle, and then you close the box by adding the first corner again. This creates a closed box that the search will perform within. </p>



<p class="wp-block-paragraph">This is an example of an approximated box within France:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
SELECT *
FROM c
WHERE ST_WITHIN(c.location, {
  "type": "Polygon",
  "coordinates": &#91;&#91;
    &#91;-5.0, 42.0],   -- Southwest corner (near Bay of Biscay)
    &#91;8.5, 42.0],    -- Southeast corner (near Mediterranean)
    &#91;8.5, 51.5],    -- Northeast corner (near Belgium/Luxembourg)
    &#91;-5.0, 51.5],   -- Northwest corner (near English Channel)
    &#91;-5.0, 42.0]    -- Closing the polygon
  ]]
})
</pre></div>


<p class="wp-block-paragraph">Notice how the coordinates are in counter clockwise order. Reversing the order will make the search fail.</p>



<p class="wp-block-paragraph">That&#8217;s it. You are now a CosmosDB and spatial search expert. Happy coding.</p>



<p class="wp-block-paragraph"><strong>MORE TO READ:</strong></p>



<ul class="wp-block-list">
<li><a href="https://geojson.org/" target="_blank" rel="noreferrer noopener">GeoJSON format specification</a></li>



<li><a href="https://geojson.io/#map=2/0/20" target="_blank" rel="noreferrer noopener">GeoJSON.io &#8211; a helpful tool to generate GeoJSON</a></li>



<li><a href="https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/query/geospatial?tabs=csharp" target="_blank" rel="noreferrer noopener">Geospatial and GeoJSON location data in Azure Cosmos DB for NoSQL</a> from Microsoft</li>



<li><a href="https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/" target="_blank" rel="noreferrer noopener">Azure Cosmos DB for NoSQL</a> from Microsoft</li>



<li><a href="https://docs.azure.cn/en-us/cosmos-db/index-policy" target="_blank" rel="noreferrer noopener">Indexing policies in Azure Cosmos DB</a> from Microsoft</li>



<li><a href="https://medium.com/ns-techblog/cosmos-db-a-versatile-tool-for-real-time-spatial-queries-b720683bff0c" target="_blank" rel="noreferrer noopener">Cosmos DB: a versatile tool for real-time (spatial) queries</a> by <a href="https://medium.com/@guusjeboomgaard?source=post_page---byline--b720683bff0c---------------------------------------" target="_blank" rel="noreferrer noopener">Guusje Boomgaard</a></li>
</ul>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://briancaos.wordpress.com/2025/06/17/c-cosmosdb-spatial-geographic-search-using-geojson-coordinates/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4051</post-id>
		<media:content medium="image" url="https://2.gravatar.com/avatar/b1cd26d13baf270ccbc554e8071367bfe693798598bb33f3784394cfde1e1537?s=96&amp;d=https%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96">
			<media:title type="html">briancaos</media:title>
		</media:content>

		<media:content medium="image" url="https://briancaos.wordpress.com/wp-content/uploads/2025/06/cosmosdbgeojson.png?w=1024">
			<media:title type="html">GeoJSON object in CosmosDB</media:title>
		</media:content>

		<media:content medium="image" url="https://briancaos.wordpress.com/wp-content/uploads/2025/06/cosmosdbspatialindexing.png?w=1024">
			<media:title type="html">Spatial Indexing Enabled</media:title>
		</media:content>
	</item>
		<item>
		<title>C# Use Microsoft Entra ID JWT token as Authentication in .net API</title>
		<link>https://briancaos.wordpress.com/2025/04/15/c-use-microsoft-entra-id-jwt-token-as-authentication-in-net-api/</link>
					<comments>https://briancaos.wordpress.com/2025/04/15/c-use-microsoft-entra-id-jwt-token-as-authentication-in-net-api/#respond</comments>
		
		<dc:creator><![CDATA[briancaos]]></dc:creator>
		<pubDate>Tue, 15 Apr 2025 08:31:14 +0000</pubDate>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[.NET Core]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[General .NET]]></category>
		<category><![CDATA[Microsoft Azure]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Authorize]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[Bearer]]></category>
		<category><![CDATA[Client Secret]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Entra]]></category>
		<category><![CDATA[JWT]]></category>
		<category><![CDATA[microsoft]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[Tenant]]></category>
		<category><![CDATA[Token]]></category>
		<guid isPermaLink="false">http://briancaos.wordpress.com/?p=4025</guid>

					<description><![CDATA[You can use Microsoft Entra ID to create a client secret that allows an application to access your API using a bearer token. STEP 1: SETUP A CLIENT SECRET IN MICROSOFT ENTRA In Microsoft Entra, take a note of the &#8230; <a href="https://briancaos.wordpress.com/2025/04/15/c-use-microsoft-entra-id-jwt-token-as-authentication-in-net-api/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">You can use Microsoft Entra ID to create a client secret that allows an application to access your API using a <a href="https://apidog.com/articles/what-is-bearer-token/" target="_blank" rel="noreferrer noopener">bearer token</a>. </p>



<p class="wp-block-paragraph"><strong>STEP 1: SETUP A CLIENT SECRET IN MICROSOFT ENTRA</strong></p>



<p class="wp-block-paragraph">In <a href="https://learn.microsoft.com/en-us/entra/fundamentals/whatis" target="_blank" rel="noreferrer noopener">Microsoft Entra</a>, take a note of the following values:</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><a href="https://briancaos.wordpress.com/wp-content/uploads/2025/04/entra001.png"><img width="934" height="251" data-attachment-id="4028" data-permalink="https://briancaos.wordpress.com/2025/04/15/c-use-microsoft-entra-id-jwt-token-as-authentication-in-net-api/entra001/" data-orig-file="https://briancaos.wordpress.com/wp-content/uploads/2025/04/entra001.png" data-orig-size="934,251" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Entra001" data-image-description="" data-image-caption="" data-large-file="https://briancaos.wordpress.com/wp-content/uploads/2025/04/entra001.png?w=640" src="https://briancaos.wordpress.com/wp-content/uploads/2025/04/entra001.png?w=934" alt="" class="wp-image-4028" srcset="https://briancaos.wordpress.com/wp-content/uploads/2025/04/entra001.png 934w, https://briancaos.wordpress.com/wp-content/uploads/2025/04/entra001.png?w=150 150w, https://briancaos.wordpress.com/wp-content/uploads/2025/04/entra001.png?w=300 300w, https://briancaos.wordpress.com/wp-content/uploads/2025/04/entra001.png?w=768 768w" sizes="(max-width: 934px) 100vw, 934px" /></a><figcaption class="wp-element-caption">You need the Application ID and Directory ID</figcaption></figure>
</div>


<p class="wp-block-paragraph">You will need the <strong>Application (client)</strong> ID and the <strong>Directory (tenant) ID</strong>.</p>



<p class="wp-block-paragraph">Then, in Microsoft Entra, you go to &#8220;<strong>Certificates &amp; secrets</strong>&#8221; and create a new secret. Copy the secret value after you have created it. You will not be able to retrieve the secret later.</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><a href="https://briancaos.wordpress.com/wp-content/uploads/2025/04/entra002.png"><img loading="lazy" width="1024" height="202" data-attachment-id="4031" data-permalink="https://briancaos.wordpress.com/2025/04/15/c-use-microsoft-entra-id-jwt-token-as-authentication-in-net-api/entra002/" data-orig-file="https://briancaos.wordpress.com/wp-content/uploads/2025/04/entra002.png" data-orig-size="1616,320" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Entra002" data-image-description="" data-image-caption="" data-large-file="https://briancaos.wordpress.com/wp-content/uploads/2025/04/entra002.png?w=640" src="https://briancaos.wordpress.com/wp-content/uploads/2025/04/entra002.png?w=1024" alt="" class="wp-image-4031" srcset="https://briancaos.wordpress.com/wp-content/uploads/2025/04/entra002.png?w=1024 1024w, https://briancaos.wordpress.com/wp-content/uploads/2025/04/entra002.png?w=150 150w, https://briancaos.wordpress.com/wp-content/uploads/2025/04/entra002.png?w=300 300w, https://briancaos.wordpress.com/wp-content/uploads/2025/04/entra002.png?w=768 768w, https://briancaos.wordpress.com/wp-content/uploads/2025/04/entra002.png?w=1440 1440w, https://briancaos.wordpress.com/wp-content/uploads/2025/04/entra002.png 1616w" sizes="(max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">Create a new secret</figcaption></figure>
</div>


<p class="wp-block-paragraph">You can now log into Microsoft Entra, and Entra will return a bearer token:</p>



<figure class="wp-block-image size-large"><a href="https://briancaos.wordpress.com/wp-content/uploads/2025/04/entralogin.png"><img loading="lazy" width="1024" height="266" data-attachment-id="4033" data-permalink="https://briancaos.wordpress.com/2025/04/15/c-use-microsoft-entra-id-jwt-token-as-authentication-in-net-api/entralogin/" data-orig-file="https://briancaos.wordpress.com/wp-content/uploads/2025/04/entralogin.png" data-orig-size="2141,557" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="EntraLogin" data-image-description="" data-image-caption="" data-large-file="https://briancaos.wordpress.com/wp-content/uploads/2025/04/entralogin.png?w=640" src="https://briancaos.wordpress.com/wp-content/uploads/2025/04/entralogin.png?w=1024" alt="" class="wp-image-4033" srcset="https://briancaos.wordpress.com/wp-content/uploads/2025/04/entralogin.png?w=1024 1024w, https://briancaos.wordpress.com/wp-content/uploads/2025/04/entralogin.png?w=2048 2048w, https://briancaos.wordpress.com/wp-content/uploads/2025/04/entralogin.png?w=150 150w, https://briancaos.wordpress.com/wp-content/uploads/2025/04/entralogin.png?w=300 300w, https://briancaos.wordpress.com/wp-content/uploads/2025/04/entralogin.png?w=768 768w, https://briancaos.wordpress.com/wp-content/uploads/2025/04/entralogin.png?w=1440 1440w" sizes="(max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">Get a bearer token from Entra</figcaption></figure>



<ul class="wp-block-list">
<li>POST to <a href="https://login.microsoftonline.com//oauth2/v2.0/token">https://login.microsoftonline.com/&lt;Directory (tenant) ID&gt;/oauth2/v2.0/token</a></li>



<li>Form Encode (x-www-form-urlencoded) values:
<ul class="wp-block-list">
<li>grant_type: client_credentials</li>



<li>client_id: Application (client) ID</li>



<li>client_secret: Certificates &amp; secrets, secret value (M2i…..)</li>



<li>scope: api://&lt;Application (client) ID&gt;/.default</li>
</ul>
</li>
</ul>



<p class="wp-block-paragraph"><strong>STEP 2: ADD AUTHENTICATION AND AUTHORIZATION TO PROGRAM.CS</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
using AuthApi.Middlewares;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Reflection;

var builder = WebApplication.CreateBuilder(args);

// ----------------------------------------------------------------
// This is the actual code that should verify the JWT token
// ----------------------------------------------------------------

// Add authentication
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =&gt;
{
  options.Authority = &quot;https://login.microsoftonline.com/&lt;Directory (tenant) ID&gt;/v2.0&quot;;
  options.TokenValidationParameters = new TokenValidationParameters
  {
    ValidateIssuer = true,
    ValidateAudience = true,
    ValidateLifetime = true,
    ValidateIssuerSigningKey = true,
    ValidIssuer = &quot;https://sts.windows.net/&lt;Directory (tenant) ID&gt;/&quot;,
    ValidAudience = &quot;api://&lt;Application (client) ID&gt;&quot;
  };
});

// Add authorization
builder.Services.AddAuthorization();

// ----------------------------------------------------------------
// This is other plumbing code
// ----------------------------------------------------------------

// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =&gt;
  {
    var xmlFilename = $&quot;{Assembly.GetExecutingAssembly().GetName().Name}.xml&quot;;
    options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
  }
);

// Logging
builder.Logging.AddConsole();
builder.Services.AddControllers();
var app = builder.Build();

// ----------------------------------------------------------------
// This is the application part. The sequence of calls is important
// ----------------------------------------------------------------

app.UseSwagger();
app.UseSwaggerUI();

app.UseHttpsRedirection();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();
</pre></div>


<p class="wp-block-paragraph">Replace <strong>&lt;Directory (tenant) ID&gt;</strong> and <strong>&lt;Application (client) ID&gt; </strong>with the IDs from Microsoft Entra.</p>



<p class="wp-block-paragraph"><strong>STEP 3: DECORATE THE API CONTROLLERS WITH [Authorize]</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; highlight: [6]; title: ; notranslate">
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace AuthApi.Controllers
{
  &#91;Authorize]  
  &#91;ApiController]
  &#91;Route(&quot;api/authtest&quot;)]
  public class AuthTestController : ControllerBase
  {
    private readonly ILogger&lt;AuthTestController&gt; _logger;

    public AuthTestController(ILogger&lt;AuthTestController&gt; logger)
    {
      _logger = logger;
    }

    &#91;HttpGet]
    public async Task&lt;IActionResult&gt; Get()
    {
      return Ok(&quot;It works!!!&quot;);
    }
  }
}

</pre></div>


<p class="wp-block-paragraph">When the controller is decorated with the [Authorize] attribute, all endpoints within this controller require authorization.</p>



<p class="wp-block-paragraph"><strong>TO TEST THE CODE:</strong></p>



<p class="wp-block-paragraph">If you try to call the API endpoint without a bearer token, or if you try to call it from Swagger, the API endpoint will return 401 unauthorized. </p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><a href="https://briancaos.wordpress.com/wp-content/uploads/2025/04/authtest001.png"><img loading="lazy" width="1024" height="334" data-attachment-id="4042" data-permalink="https://briancaos.wordpress.com/2025/04/15/c-use-microsoft-entra-id-jwt-token-as-authentication-in-net-api/authtest001/" data-orig-file="https://briancaos.wordpress.com/wp-content/uploads/2025/04/authtest001.png" data-orig-size="1783,583" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="AuthTest001" data-image-description="" data-image-caption="" data-large-file="https://briancaos.wordpress.com/wp-content/uploads/2025/04/authtest001.png?w=640" src="https://briancaos.wordpress.com/wp-content/uploads/2025/04/authtest001.png?w=1024" alt="" class="wp-image-4042" srcset="https://briancaos.wordpress.com/wp-content/uploads/2025/04/authtest001.png?w=1024 1024w, https://briancaos.wordpress.com/wp-content/uploads/2025/04/authtest001.png?w=150 150w, https://briancaos.wordpress.com/wp-content/uploads/2025/04/authtest001.png?w=300 300w, https://briancaos.wordpress.com/wp-content/uploads/2025/04/authtest001.png?w=768 768w, https://briancaos.wordpress.com/wp-content/uploads/2025/04/authtest001.png?w=1440 1440w, https://briancaos.wordpress.com/wp-content/uploads/2025/04/authtest001.png 1783w" sizes="(max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">401 unauthorized is returned when you call the endpoint without a bearer token</figcaption></figure>
</div>


<p class="wp-block-paragraph">But if you first get a bearer token by POSTing to &lt;a href=&quot;<a href="https://login.microsoftonline.com/https://login.microsoftonline.com/&lt;Directory" rel="nofollow">https://login.microsoftonline.com/https://login.microsoftonline.com/&lt;Directory</a> (tenant) ID&gt;/oauth2/v2.0/token</a> with the correct secret, and use this bearer token in the header, the API endpoint responds:</p>



<figure class="wp-block-image size-large"><a href="https://briancaos.wordpress.com/wp-content/uploads/2025/04/authtest002.png"><img loading="lazy" width="1024" height="448" data-attachment-id="4045" data-permalink="https://briancaos.wordpress.com/2025/04/15/c-use-microsoft-entra-id-jwt-token-as-authentication-in-net-api/authtest002/" data-orig-file="https://briancaos.wordpress.com/wp-content/uploads/2025/04/authtest002.png" data-orig-size="1162,509" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="AuthTest002" data-image-description="" data-image-caption="" data-large-file="https://briancaos.wordpress.com/wp-content/uploads/2025/04/authtest002.png?w=640" src="https://briancaos.wordpress.com/wp-content/uploads/2025/04/authtest002.png?w=1024" alt="" class="wp-image-4045" srcset="https://briancaos.wordpress.com/wp-content/uploads/2025/04/authtest002.png?w=1024 1024w, https://briancaos.wordpress.com/wp-content/uploads/2025/04/authtest002.png?w=150 150w, https://briancaos.wordpress.com/wp-content/uploads/2025/04/authtest002.png?w=300 300w, https://briancaos.wordpress.com/wp-content/uploads/2025/04/authtest002.png?w=768 768w, https://briancaos.wordpress.com/wp-content/uploads/2025/04/authtest002.png 1162w" sizes="(max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">With the proper bearer token, the API endpoint will work</figcaption></figure>



<p class="wp-block-paragraph">This is the basics of Entra IDs and bearer tokens. Happy coding.</p>



<p class="wp-block-paragraph"><strong>MORE TO READ:</strong></p>



<ul class="wp-block-list">
<li><a href="https://learn.microsoft.com/en-us/entra/identity-platform/access-tokens" target="_blank" rel="noreferrer noopener">Access tokens in the Microsoft identity platform</a> from Microsoft</li>



<li><a href="https://www.xintra.org/blog/tokens-in-entra-id-guide" target="_blank" rel="noreferrer noopener">Understanding Tokens in Entra ID: A Comprehensive Guide</a> by Lina Lau</li>



<li><a href="https://github.com/MicrosoftDocs/entra-docs/blob/main/docs/identity-platform/access-token-claims-reference.md" target="_blank" rel="noreferrer noopener">Access token claims reference</a> from MicrosoftDocs</li>



<li><a href="https://apidog.com/articles/what-is-bearer-token/" target="_blank" rel="noreferrer noopener">What is Bearer Token and How it Works?</a> from ApiDog</li>



<li><a href="https://learn.microsoft.com/en-us/entra/fundamentals/whatis" target="_blank" rel="noreferrer noopener">What is Microsoft Entra ID?</a> from Microsoft</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://briancaos.wordpress.com/2025/04/15/c-use-microsoft-entra-id-jwt-token-as-authentication-in-net-api/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4025</post-id>
		<media:content medium="image" url="https://2.gravatar.com/avatar/b1cd26d13baf270ccbc554e8071367bfe693798598bb33f3784394cfde1e1537?s=96&amp;d=https%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96">
			<media:title type="html">briancaos</media:title>
		</media:content>

		<media:content medium="image" url="https://briancaos.wordpress.com/wp-content/uploads/2025/04/entra001.png?w=934"/>

		<media:content medium="image" url="https://briancaos.wordpress.com/wp-content/uploads/2025/04/entra002.png?w=1024"/>

		<media:content medium="image" url="https://briancaos.wordpress.com/wp-content/uploads/2025/04/entralogin.png?w=1024"/>

		<media:content medium="image" url="https://briancaos.wordpress.com/wp-content/uploads/2025/04/authtest001.png?w=1024"/>

		<media:content medium="image" url="https://briancaos.wordpress.com/wp-content/uploads/2025/04/authtest002.png?w=1024"/>
	</item>
		<item>
		<title>C# Serialize HttpRequest to Model Class in Azure Functions</title>
		<link>https://briancaos.wordpress.com/2025/04/08/c-serialize-httprequest-to-model-class-in-azure-functions/</link>
					<comments>https://briancaos.wordpress.com/2025/04/08/c-serialize-httprequest-to-model-class-in-azure-functions/#respond</comments>
		
		<dc:creator><![CDATA[briancaos]]></dc:creator>
		<pubDate>Tue, 08 Apr 2025 07:52:00 +0000</pubDate>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[.NET Core]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[General .NET]]></category>
		<category><![CDATA[Microsoft Azure]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[Azure Function]]></category>
		<category><![CDATA[Azure Functions]]></category>
		<category><![CDATA[Deserialize]]></category>
		<category><![CDATA[httpRequestBegin]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[serialize]]></category>
		<category><![CDATA[System.Text.Json]]></category>
		<guid isPermaLink="false">http://briancaos.wordpress.com/?p=4014</guid>

					<description><![CDATA[The signature of Http triggered Azure Functions include a HttpRequest: The HttpRequest is not serialized by default, as it is when working with controllers in .net. So we need to do it ourselves. This can be achieved with a simple &#8230; <a href="https://briancaos.wordpress.com/2025/04/08/c-serialize-httprequest-to-model-class-in-azure-functions/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">The signature of Http triggered Azure Functions include a <a href="https://learn.microsoft.com/en-us/dotnet/api/system.web.httprequest?view=netframework-4.8.1&amp;viewFallbackFrom=net-10.0" target="_blank" rel="noreferrer noopener">HttpRequest</a>:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
&#91;Function(&quot;MyFunction&quot;)]
public async Task&lt;IActionResult&gt; Run(&#91;HttpTrigger(AuthorizationLevel.Function, &quot;post&quot;)] HttpRequest req)
{
  // first order of things is to get the request body and serialize it into a class
}
</pre></div>


<p class="wp-block-paragraph">The <strong>HttpRequest</strong> is not serialized by default, as it is when working with controllers in .net. So we need to do it ourselves.</p>



<p class="wp-block-paragraph">This can be achieved with a simple extension method:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
using Microsoft.AspNetCore.Http;

namespace AzureFunctionApp.Foundation.Extensions
{
    public static class HttpRequestExtension
    {
        public static async Task&lt;T?&gt; DeserializeAsync&lt;T&gt;(this HttpRequest req)
        {
            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            var options = new System.Text.Json.JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true
            };
            return System.Text.Json.JsonSerializer.Deserialize&lt;T&gt;(requestBody, options);
        }
    }
}
</pre></div>


<p class="wp-block-paragraph">Now, in the Azure Function, the first line of code will be to read the body into a model class:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
&#91;Function(&quot;MyFunction&quot;)]
public async Task&lt;IActionResult&gt; Run(&#91;HttpTrigger(AuthorizationLevel.Function, &quot;post&quot;)] HttpRequest req)
{
  // first order of things is to get the request body and serialize it into a class
  var request = await req.DeserializeAsync&lt;MyModelClass&gt;();
  
  // now you can work with the data from the request body:
  var field = request.SomeField;
}
</pre></div>


<p class="wp-block-paragraph">That&#8217;s it. You are now an Azure Function expert. Happy coding.</p>



<p class="wp-block-paragraph"><strong>MORE TO READ:</strong></p>



<ul class="wp-block-list">
<li><a href="https://learn.microsoft.com/en-us/dotnet/api/system.web.httprequest?view=netframework-4.8.1&amp;viewFallbackFrom=net-10.0" target="_blank" rel="noreferrer noopener">HttpRequest Class</a> from Microsoft</li>



<li><a href="https://briancaos.wordpress.com/2024/09/13/azure-functions-no-job-functions-found-try-making-your-job-classes-and-methods-public/" target="_blank" rel="noreferrer noopener">Azure Functions: No job functions found. Try making your job classes and methods public.</a> by briancaos</li>
</ul>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://briancaos.wordpress.com/2025/04/08/c-serialize-httprequest-to-model-class-in-azure-functions/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4014</post-id>
		<media:content medium="image" url="https://2.gravatar.com/avatar/b1cd26d13baf270ccbc554e8071367bfe693798598bb33f3784394cfde1e1537?s=96&amp;d=https%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96">
			<media:title type="html">briancaos</media:title>
		</media:content>
	</item>
		<item>
		<title>Azure Table Storage Create Read Update Delete entities – a base class implementation using C#</title>
		<link>https://briancaos.wordpress.com/2025/03/10/azure-table-storage-create-read-update-delete-entities-a-base-class-implementation-using-c/</link>
					<comments>https://briancaos.wordpress.com/2025/03/10/azure-table-storage-create-read-update-delete-entities-a-base-class-implementation-using-c/#respond</comments>
		
		<dc:creator><![CDATA[briancaos]]></dc:creator>
		<pubDate>Mon, 10 Mar 2025 10:50:53 +0000</pubDate>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[.NET Core]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[General .NET]]></category>
		<category><![CDATA[Microsoft Azure]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[ITableEntity]]></category>
		<category><![CDATA[llm]]></category>
		<category><![CDATA[NoSql]]></category>
		<category><![CDATA[Partition]]></category>
		<category><![CDATA[Table Storage]]></category>
		<category><![CDATA[Table Store]]></category>
		<guid isPermaLink="false">http://briancaos.wordpress.com/?p=3998</guid>

					<description><![CDATA[Azure Table Storage is a simple way of storing structured data with no relations (also known as structured NoSQL data) in a storage account. Think of it as an spreadsheet with 2 mandatory keys (a partition key and a row &#8230; <a href="https://briancaos.wordpress.com/2025/03/10/azure-table-storage-create-read-update-delete-entities-a-base-class-implementation-using-c/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Azure Table Storage is a simple way of storing structured data with no relations (also known as structured NoSQL data) in a storage account. Think of it as an spreadsheet with 2 mandatory keys (a partition key and a row key).</p>



<figure class="wp-block-image size-large"><a href="https://briancaos.wordpress.com/wp-content/uploads/2025/03/tablestorage.png"><img loading="lazy" width="1024" height="204" data-attachment-id="4001" data-permalink="https://briancaos.wordpress.com/2025/03/10/azure-table-storage-create-read-update-delete-entities-a-base-class-implementation-using-c/tablestorage-2/" data-orig-file="https://briancaos.wordpress.com/wp-content/uploads/2025/03/tablestorage.png" data-orig-size="2008,401" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="TableStorage" data-image-description="" data-image-caption="" data-large-file="https://briancaos.wordpress.com/wp-content/uploads/2025/03/tablestorage.png?w=640" src="https://briancaos.wordpress.com/wp-content/uploads/2025/03/tablestorage.png?w=1024" alt="Simple Table Storage Table" class="wp-image-4001" srcset="https://briancaos.wordpress.com/wp-content/uploads/2025/03/tablestorage.png?w=1024 1024w, https://briancaos.wordpress.com/wp-content/uploads/2025/03/tablestorage.png?w=150 150w, https://briancaos.wordpress.com/wp-content/uploads/2025/03/tablestorage.png?w=300 300w, https://briancaos.wordpress.com/wp-content/uploads/2025/03/tablestorage.png?w=768 768w, https://briancaos.wordpress.com/wp-content/uploads/2025/03/tablestorage.png?w=1440 1440w, https://briancaos.wordpress.com/wp-content/uploads/2025/03/tablestorage.png 2008w" sizes="(max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">Simple Table Storage Table</figcaption></figure>



<p class="wp-block-paragraph">The data you insert is called entities, and in C# you implement the <a href="https://learn.microsoft.com/en-us/dotnet/api/azure.data.tables.itableentity?view=azure-dotnet" target="_blank" rel="noreferrer noopener">ITableEntity</a> interface to create a class that can be inserted into a table.</p>



<p class="wp-block-paragraph">With a little bit of plumbing code you can create a base class that overcomes the limitations of the Table Storage.</p>



<p class="wp-block-paragraph">This GIT repository contains a simple base class implementation that makes it easy to do CRUD operations on a Table Storage:</p>



<p class="has-text-align-center wp-block-paragraph"><a href="https://github.com/briancaos/azuretablerepository">https://github.com/briancaos/azuretablerepository</a></p>



<p class="wp-block-paragraph">It simplifies several things:</p>



<ul class="wp-block-list">
<li>It uses strong types.</li>



<li>Read an entire table without paging.</li>



<li>No size limit when bulk insert, update, delete.</li>
</ul>



<p class="wp-block-paragraph"><strong>HOW TO SET UP THE BASE CLASS</strong></p>



<p class="wp-block-paragraph"><strong>STEP 1: Implement a ITableEntity class</strong></p>



<p class="wp-block-paragraph">This class is the contents of your table. This is an example class:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
public class MyEntity : ITableEntity
{
  /// &lt;summary&gt;
  /// Mandatory field (partition id)
  /// &lt;/summary&gt;
  public string? PartitionKey { get; set; }
  /// &lt;summary&gt;
  /// Mandatory field (row id)
  /// &lt;/summary&gt;
  public string? RowKey { get; set; }
  /// &lt;summary&gt;
  /// Mandatory field (last modified)
  /// &lt;/summary&gt;
  public DateTimeOffset? Timestamp { get; set; } = default!;
  /// &lt;summary&gt;
  /// Mandatory field (unique id)
  /// &lt;/summary&gt;
  public ETag ETag { get; set; } = default!;

  /// &lt;summary&gt;
  /// Custom table field
  /// &lt;/summary&gt;
  public string? Value1 { get; set; } 
}
</pre></div>


<p class="wp-block-paragraph"><strong>STEP 2: Create a concrete implementation of the class</strong></p>



<p class="wp-block-paragraph">In this class you specify the name of the table to store your &#8220;MyEntity&#8221;. And you give base class the name of the ITableEntity to store in that table.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
using Azure.Data.Tables;

namespace MyCode
{
    public class MyRepository : AzureTableBaseRepository&lt;MyEntity&gt;
    {
        public MyRepository(TableServiceClient tableServiceClient) : base(&quot;MyTable&quot;, tableServiceClient)
        {
        }
    }
}

</pre></div>


<p class="wp-block-paragraph"><strong>STEP 3: Setup dependency injection in Program.cs</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
// Creating a connection to a storage account containing the 
// Azure Table
builder.Services.AddAzureClients(context =&gt; context.AddTableServiceClient(builder.Configuration.GetConnectionString(&quot;StorageAccount&quot;)));
// Allowing for depencency injection
builder.Services.AddTransient&lt;MyRepository&gt;();
</pre></div>


<p class="wp-block-paragraph"><strong>HOW TO USE THE REPOSITORY</strong></p>



<p class="wp-block-paragraph"><strong>Injecting class into other class</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
public class MyClass 
{
    private MyRepository _myRepository;

    public MyClass(MyRepository myRepository)
    {
        _myRepository = myRepository;
    }

    ...
    ...
}
</pre></div>


<p class="wp-block-paragraph"><strong>Create, Update, or Upsert 1 entity</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
var entity = new MyEntity() 
{ 
    PartitionKey = "partition",
    RowKey = "row001",
    Value1 = "myvalue"
};

// Adds a new row. Will fail if the partitionkey/rowkey already exists
await _myRepository.AddAsync(entity);

// Updates a row. Will fail if the partitionkey/rowkey does not exist
await _myRepository.UpdateAsync(entity);

// If entity exists, updates the entity. If not, a new is created
await _myRepository.UpsertAsync(entity);

</pre></div>


<p class="wp-block-paragraph"><strong>Handle concurrency issues on update</strong></p>



<p class="wp-block-paragraph">You can use the <em>UpdateAsync(T entity, ETag ifMatch, TableUpdateMode tableUpdateMode)</em> method to handle concurrency issues:<br></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
int maxRetries = 10;
int retryCount = 0;
while (retryCount &lt; maxRetries)
{
    try
    {
        var entity = _myRepository.GetAsync(&quot;partition&quot;, &quot;row001&quot;);
        entity.Value1 = entity.Value1 + &quot;1&quot;;
        await _myRepository.UpdateAsync(entity, entity.ETag, TableUpdateMode.Replace);
        break;
    }
    // 412 = Precondition Failed (ETag mismatch)
    catch (RequestFailedException ex) when (ex.Status == 412) 
    {
        retryCount++;
        if (retryCount == maxRetries)
        {
            throw new Exception(&quot;Cannot update entity&quot;);
        }
        else
        {
            // Exponential backoff (0.5s, 1s, 1.5s, ...)
            await Task.Delay(500 * retryCount);
        }
    }
}
</pre></div>


<p class="wp-block-paragraph"><strong>Create, Update, or Upsert many entities</strong></p>



<p class="wp-block-paragraph">In these methods, you don&#8217;t need to worry about the insert limits of Azure Tables, the class will chunk your array for you.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
List&lt;MyEntity&gt; entityList = new List&lt;MyEntity&gt;();

for (int i=0;i&lt;100;i++)
{
    var entity = new MyEntity() 
    { 
        PartitionKey = &quot;partition&quot;,
        RowKey = &quot;row&quot; + i,
        Value1 = &quot;myvalue&quot;
    };
}

// Adds new rows. Will fail if the partitionkeys/rowkeys already exists
await _myRepository.AddAsync(entityList);

// Updates rows. Will fail if the partitionkeys/rowkeys does not exist
await _myRepository.UpdateAsync(entityList);

// If entities exists, updates the entities. If not, new entities are created
await _myRepository.UpsertAsync(entityList);
</pre></div>


<p class="wp-block-paragraph"><strong>Read entities</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
// One specific entity
var entity = await _myRepository.GetAsync(&quot;partition&quot;, &quot;row001&quot;);

// Using LINQ to query table. Returns all entities matching the 
// query.
var entities = await _myRepository.GetAsync(e =&gt; e.PartitionKey == &quot;partition&quot;);
</pre></div>


<p class="wp-block-paragraph">That&#8217;s it. You are now a Azure Table Storage expert. Happy coding.</p>



<p class="wp-block-paragraph"><strong>MORE TO READ:</strong></p>



<ul class="wp-block-list">
<li><a href="https://briancaos.wordpress.com/2022/11/11/c-azure-table-storage-queryasync-paging-and-filtering/" target="_blank" rel="noreferrer noopener">C# Azure Table Storage QueryAsync, Paging and&nbsp;Filtering</a> by briancaos</li>



<li><a href="https://andysprague.com/2020/12/04/azure-table-storage-queryasync/" target="_blank" rel="noreferrer noopener">Azure Table Storage –&nbsp;QueryAsync</a> by andysprague</li>



<li><a href="https://learn.microsoft.com/en-us/dotnet/api/azure.data.tables.itableentity?view=azure-dotnet" target="_blank" rel="noreferrer noopener">ITableEntity Interface</a> from microsoft</li>



<li><a href="https://learn.microsoft.com/en-us/azure/storage/tables/table-storage-overview" target="_blank" rel="noreferrer noopener">What is Azure Table storage?</a> from microsoft</li>
</ul>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://briancaos.wordpress.com/2025/03/10/azure-table-storage-create-read-update-delete-entities-a-base-class-implementation-using-c/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3998</post-id>
		<media:content medium="image" url="https://2.gravatar.com/avatar/b1cd26d13baf270ccbc554e8071367bfe693798598bb33f3784394cfde1e1537?s=96&amp;d=https%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96">
			<media:title type="html">briancaos</media:title>
		</media:content>

		<media:content medium="image" url="https://briancaos.wordpress.com/wp-content/uploads/2025/03/tablestorage.png?w=1024">
			<media:title type="html">Simple Table Storage Table</media:title>
		</media:content>
	</item>
		<item>
		<title>Connect to Salesforce Data Cloud Ingestion API using C# and HttpClient</title>
		<link>https://briancaos.wordpress.com/2024/11/26/connect-to-salesforce-data-cloud-ingestion-api-using-c-and-httpclient/</link>
					<comments>https://briancaos.wordpress.com/2024/11/26/connect-to-salesforce-data-cloud-ingestion-api-using-c-and-httpclient/#respond</comments>
		
		<dc:creator><![CDATA[briancaos]]></dc:creator>
		<pubDate>Tue, 26 Nov 2024 10:36:56 +0000</pubDate>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[.NET Core]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[General .NET]]></category>
		<category><![CDATA[Access]]></category>
		<category><![CDATA[Authentication]]></category>
		<category><![CDATA[Authorization]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Data Cloud]]></category>
		<category><![CDATA[HttpClient]]></category>
		<category><![CDATA[IHttpClientFactory]]></category>
		<category><![CDATA[Ingest]]></category>
		<category><![CDATA[Ingestion]]></category>
		<category><![CDATA[JWT]]></category>
		<category><![CDATA[OAuth]]></category>
		<category><![CDATA[OAuth2]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[Salesforce]]></category>
		<category><![CDATA[security]]></category>
		<guid isPermaLink="false">http://briancaos.wordpress.com/?p=3981</guid>

					<description><![CDATA[As a C# developer, to properly connect to Salesforce Data Cloud, you need to do 3 steps: So in other words, you do authorization twice before you can POST your JSON to an Ingestion endpoint. So let&#8217;s get started. BEFORE &#8230; <a href="https://briancaos.wordpress.com/2024/11/26/connect-to-salesforce-data-cloud-ingestion-api-using-c-and-httpclient/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">As a C# developer, to properly connect to <a href="https://developer.salesforce.com/docs/platform/data-cloud-dev/guide/get-started.htm" target="_blank" rel="noreferrer noopener">Salesforce Data Cloud</a>, you need to do 3 steps:</p>



<ol class="wp-block-list">
<li>Request an <strong>Access Token</strong> using the credentials provided for you.</li>



<li>Exchange the Access Token for a <strong>Data Cloud Token</strong></li>



<li>POST data to the <strong>Ingestion API</strong> using the Data Cloud Token</li>
</ol>



<p class="wp-block-paragraph">So in other words, you do authorization twice before you can POST your JSON to an <a href="https://help.salesforce.com/s/articleView?id=sf.c360_a_ingestion_api.htm&amp;type=5" target="_blank" rel="noreferrer noopener">Ingestion endpoint</a>. So let&#8217;s get started.</p>



<p class="wp-block-paragraph"><strong>BEFORE WE BEGIN: THE PREREQUISITES</strong></p>



<p class="wp-block-paragraph">As a responsible developer, we use the <a href="https://briancaos.wordpress.com/2023/04/21/c-httpclient-and-ihttpclientfactory-in-net-core/" target="_blank" rel="noreferrer noopener">HttpClientFactory to create a HttpClient</a>. So in the Program.cs, we have implemented an <strong>IHttpClientFactory </strong>instance:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
services.AddHttpClient("httpClient");
</pre></div>


<p class="wp-block-paragraph"><strong>STEP 1: REQUEST AN ACCESS TOKEN USING BASIC AUTHENTICATION</strong></p>



<p class="wp-block-paragraph">The AccessToken is in the format of an <strong>OAuth token</strong>, so we create a class for that:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
using System.Text.Json.Serialization;

namespace AzureFunctionApp.Salesforce
{
  public class OAuthToken
  {
        &#91;JsonPropertyName("access_token")]
        public string AccessToken { get; set; }

        &#91;JsonPropertyName("signature")]
        public string Signature { get; set; }

        &#91;JsonPropertyName("scope")]
        public string Scope { get; set; }

        &#91;JsonPropertyName("instance_url")]
        public string InstanceUrl { get; set; }

        &#91;JsonPropertyName("id")]
        public string Id { get; set; }

        &#91;JsonPropertyName("token_type")]
        public string TokenType { get; set; }

        &#91;JsonPropertyName("issued_at")]
        public string IssuedAt { get; set; }
    } 
}
</pre></div>


<p class="wp-block-paragraph"> Then we can create a function that gets an <strong>OAuthToken </strong>from Salesforce:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
using System.Net.Http.Json;
using System.Text;

namespace MyCode
{
  public class SalesforceRepository
  {
    private IHttpClientFactory _httpClientFactory;

    public SalesforceAccessRepository(IHttpClientFactory httpClientFactory)
    {
      _httpClientFactory = httpClientFactory;
    }

    public async Task&lt;OAuthToken?&gt; GetOAuthTokenAsync()
    {
      string? username = &quot;xxxxx&quot;;
      string? password = &quot;xxxxx&quot;;
      string? oAuthUrl = &quot;https://xxxxx.my.salesforce.com/services/oauth2/token&quot;

      var client = _httpClientFactory.CreateClient(&quot;HttpClient&quot;);
      var authToken = Encoding.ASCII.GetBytes($&quot;{username}:{password}&quot;);
      client.DefaultRequestHeaders.Authorization = 
	      new System.Net.Http.Headers.AuthenticationHeaderValue(&quot;Basic&quot;, Convert.ToBase64String(authToken));
      var content = new MultipartFormDataContent { { new StringContent(&quot;client_credentials&quot;), &quot;grant_type&quot; } };

      var response = await client.PostAsync(oAuthUrl, content);
      if (!response.IsSuccessStatusCode)
        throw new Exception($&quot;{response.StatusCode}: {response.ReasonPhrase}&quot;);

      var responseJson = await response.Content.ReadFromJsonAsync&lt;OAuthToken&gt;();
      return responseJson;
    }
  }
}

</pre></div>


<p class="wp-block-paragraph"><strong>STEP 2: EXCHANGE THE ACCESS TOKEN FOR A DATA CLOUD TOKEN</strong></p>



<p class="wp-block-paragraph">The <strong>Data Cloud token</strong> is in the format of a <strong>Json Web Token (JWT)</strong>, so we need a class for that:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
using System.Text.Json.Serialization;

namespace MyCode
{
  public class JsonWebToken
  {
    &#91;JsonPropertyName("access_token")]
    public string AccessToken {  get; set; } 

    &#91;JsonPropertyName("instance_url")]
    public string InstanceUrl {  get; set; } 

    &#91;JsonPropertyName("token_type")]
    public string TokenType { get; set; }  

    &#91;JsonPropertyName("issued_token_type")]
    public string IssuedTokenType { get; set; }  

    &#91;JsonPropertyName("expires_in")]
    public int ExpiresIn { get; set; } 

  }
}
</pre></div>


<p class="wp-block-paragraph">Then we can create another method in the SalesforceRepository from <strong>STEP1</strong>:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
    public async Task&lt;JsonWebToken?&gt; GetJsonWebTokenAsync(string bearerToken)
    {
      string? url = &quot;https://xxxxx.my.salesforce.com/services/a360/token&quot;;

      var client = _httpClientFactory.CreateClient(&quot;HttpClient&quot;);
      var data = new&#91;]
      {
        new KeyValuePair&lt;string, string&gt;(&quot;grant_type&quot;, &quot;urn:salesforce:grant-type:external:cdp&quot;),
        new KeyValuePair&lt;string, string&gt;(&quot;subject_token&quot;, bearerToken),
        new KeyValuePair&lt;string, string&gt;(&quot;subject_token_type&quot;, &quot;urn:ietf:params:oauth:token-type:access_token&quot;)
      };
      var content = new FormUrlEncodedContent(data);

      var response = await client.PostAsync(url, content);
      if (!response.IsSuccessStatusCode)
        throw new Exception($&quot;{response.StatusCode}: {response.ReasonPhrase}&quot;);

      var responseJson = await response.Content.ReadFromJsonAsync&lt;JsonWebToken&gt;();
      return responseJson;
    }

</pre></div>


<p class="wp-block-paragraph"><strong>STEP 3: POST DATA TO THE INGESTION API</strong></p>



<p class="wp-block-paragraph">With the 2 authorization function, we are now read to POST some data to an <strong>ingestion endpoint</strong>:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; title: ; notranslate">
    public async Task&lt;string&gt; Ingest(string jsonData)
    {
      OAuthToken? oauthToken = await GetOAuthTokenAsync();
      JsonWebToken? jwt = await GetJsonWebTokenAsync(oauthToken.AccessToken);
      string? accessToken = jwt?.AccessToken;  

      var client = _httpClientFactory.CreateClient(&quot;HttpClient&quot;);
      client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue(&quot;Bearer&quot;, accessToken);

      using (var content = new StringContent(jsonData, Encoding.UTF8, &quot;application/json&quot;))
      {
        var response = await client.PostAsync(&quot;https://xxxxx.salesforce.com/api/v1/ingest/sources/xxxxx&quot;, content);
        if (!response.IsSuccessStatusCode)
          throw new Exception($&quot;{response.StatusCode}: {response.ReasonPhrase}&quot;);

        var responseJson = await response.Content.ReadAsStringAsync();
        return responseJson;
      }
    }
</pre></div>


<p class="wp-block-paragraph">Please note that the Salesforce Ingestion API returns <a href="https://briancaos.wordpress.com/2019/06/19/200-ok-vs-202-accepted-whats-the-difference/" target="_blank" rel="noreferrer noopener">202 Accepted, not 200 OK</a>. 202 Accepted means that Salesforce have received the data and will look at them at some point. It does not mean that the JSON you posted is in the correct format nor that the data write is successful. </p>



<p class="wp-block-paragraph">That&#8217;s it. You are now a Salesforce expert. Happy coding.</p>



<p class="wp-block-paragraph"><strong>MORE TO READ:</strong></p>



<ul class="wp-block-list">
<li><a href="https://developer.salesforce.com/docs/atlas.en-us.c360a_api.meta/c360a_api/c360a_getting_started_with_cdp.htm" target="_blank" rel="noreferrer noopener">Salesforce Data Cloud Reference. Getting started</a> from Salesforce </li>



<li><a href="https://developer.salesforce.com/docs/marketing/marketing-cloud-growth/guide/mc-connect-apis-data-cloud.html" target="_blank" rel="noreferrer noopener">Connect to the Data Cloud API</a> from Salesforce</li>



<li><a href="https://briancaos.wordpress.com/2023/04/21/c-httpclient-and-ihttpclientfactory-in-net-core/" target="_blank" rel="noreferrer noopener">C# HttpClient and IHttpClientFactory in .net core</a> by briancaos</li>



<li><a href="https://briancaos.wordpress.com/2024/11/26/c-post-x-www-form-urlencoded-using-httpclient/">C# POST x-www-form-urlencoded</a><a href="https://briancaos.wordpress.com/2024/11/26/c-post-x-www-form-urlencoded-using-httpclient/" target="_blank" rel="noreferrer noopener"> </a><a href="https://briancaos.wordpress.com/2024/11/26/c-post-x-www-form-urlencoded-using-httpclient/">using HttpClient</a> by briancaos</li>



<li><a href="https://stackoverflow.com/questions/69799858/how-to-retrieve-data-from-salesforce-using-c-sharp" target="_blank" rel="noreferrer noopener">How to retrieve data from SalesForce using C#</a> from StackOverflow</li>



<li><a href="https://dev.to/rachelsoderberg/integrating-c-net-and-salesforce-s-rest-api-d00" target="_blank" rel="noreferrer noopener">Integrating C# .NET and Salesforce&#8217;s REST API</a> by Rachel Soderberg</li>



<li><a href="https://briancaos.wordpress.com/2023/06/07/c-jwt-token-get-expiry-timestamp/" target="_blank" rel="noreferrer noopener">C# JWT Token Get Expiry Timestamp</a> from briancaos</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://briancaos.wordpress.com/2024/11/26/connect-to-salesforce-data-cloud-ingestion-api-using-c-and-httpclient/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3981</post-id>
		<media:content medium="image" url="https://2.gravatar.com/avatar/b1cd26d13baf270ccbc554e8071367bfe693798598bb33f3784394cfde1e1537?s=96&amp;d=https%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96">
			<media:title type="html">briancaos</media:title>
		</media:content>
	</item>
		<item>
		<title>C# POST x-www-form-urlencoded using HttpClient</title>
		<link>https://briancaos.wordpress.com/2024/11/26/c-post-x-www-form-urlencoded-using-httpclient/</link>
					<comments>https://briancaos.wordpress.com/2024/11/26/c-post-x-www-form-urlencoded-using-httpclient/#comments</comments>
		
		<dc:creator><![CDATA[briancaos]]></dc:creator>
		<pubDate>Tue, 26 Nov 2024 09:59:59 +0000</pubDate>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[.NET Core]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[General .NET]]></category>
		<category><![CDATA[Form]]></category>
		<category><![CDATA[Form Data]]></category>
		<category><![CDATA[HttpClient]]></category>
		<category><![CDATA[IHttpClientFactory]]></category>
		<category><![CDATA[Post]]></category>
		<category><![CDATA[urlencode]]></category>
		<category><![CDATA[x-www-form-urlencoded]]></category>
		<guid isPermaLink="false">http://briancaos.wordpress.com/?p=3972</guid>

					<description><![CDATA[To POST x-www-form-urlencoded data in C# using the HttpClient, you can do the following: The FormUrlEncodedContent will automatically set the content-type to application/x-www-form-urlencoded. Before using the HttpClient, consider using a HttpClientFactory, as the HttpClient is a shared object and creating &#8230; <a href="https://briancaos.wordpress.com/2024/11/26/c-post-x-www-form-urlencoded-using-httpclient/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">To POST x-www-form-urlencoded data in C# using the <a href="https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=net-9.0" target="_blank" rel="noreferrer noopener">HttpClient</a>, you can do the following:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; highlight: [13]; title: ; notranslate">
using System.Net.Http;
 
private static HttpClient _httpClient = new HttpClient();

public async Task&lt;string&gt; PostFormUrlEncodedData()
{
    var data = new&#91;]
    {
        new KeyValuePair&lt;string, string&gt;(&quot;formfield1&quot;, &quot;formvalue1&quot;),
        new KeyValuePair&lt;string, string&gt;(&quot;formfield2&quot;, &quot;formvalue2&quot;),
        new KeyValuePair&lt;string, string&gt;(&quot;formfield3&quot;, &quot;formvalue3&quot;)
    };
    var content = new FormUrlEncodedContent(data);

    var response = await client.PostAsync(url, content);
    if (!response.IsSuccessStatusCode)
        throw new Exception($&quot;{response.StatusCode}: {response.ReasonPhrase}&quot;);

    var responseJson = await response.Content.ReadAsStringAsync();
      return responseJson;	
}
</pre></div>


<p class="wp-block-paragraph">The FormUrlEncodedContent will automatically set the content-type to <strong>application/x-www-form-urlencoded</strong>.</p>



<p class="wp-block-paragraph">Before using the HttpClient, consider using a <a href="https://briancaos.wordpress.com/2023/04/21/c-httpclient-and-ihttpclientfactory-in-net-core/" target="_blank" rel="noreferrer noopener">HttpClientFactory</a>, as the HttpClient is a shared object and creating a HttpClient for each call will lead to socket exhaustion.</p>



<p class="wp-block-paragraph"><strong>MORE TO READ:</strong></p>



<ul class="wp-block-list">
<li><a href="https://briancaos.wordpress.com/2023/04/28/c-use-httpclient-to-get-json-from-api-endpoint/" target="_blank" rel="noreferrer noopener">C# Use HttpClient to GET JSON from API endpoint</a> by briancaos</li>



<li><a href="https://softwareengineering.stackexchange.com/questions/418967/is-it-bad-practice-to-mutate-your-httpclient-objects" target="_blank" rel="noreferrer noopener">Is it bad practice to mutate your HttpClient objects?</a> from stackexchange</li>



<li><a href="https://briancaos.wordpress.com/2023/04/21/c-httpclient-and-ihttpclientfactory-in-net-core/">C# HttpClient and IHttpClientFactory in .net core</a> by briancaos</li>



<li><a href="https://briancaos.wordpress.com/2019/08/28/httpclient-post-or-put-json-with-content-type-application-json/" target="_blank" rel="noreferrer noopener">C# HttpClient POST or PUT Json with content type application/json</a> by briancaos</li>



<li><a href="https://briancaos.wordpress.com/2017/11/03/using-c-httpclient-from-sync-and-async-code/" target="_blank" rel="noreferrer noopener">Using C# HttpClient from Sync and Async code</a> by briancaos</li>
</ul>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://briancaos.wordpress.com/2024/11/26/c-post-x-www-form-urlencoded-using-httpclient/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3972</post-id>
		<media:content medium="image" url="https://2.gravatar.com/avatar/b1cd26d13baf270ccbc554e8071367bfe693798598bb33f3784394cfde1e1537?s=96&amp;d=https%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96">
			<media:title type="html">briancaos</media:title>
		</media:content>
	</item>
		<item>
		<title>Convert JSON Arrays into batches of JSON Arrays using the LINQ Chunk method</title>
		<link>https://briancaos.wordpress.com/2024/11/14/convert-json-arrays-into-batches-of-json-arrays-using-the-linq-chunk-method/</link>
					<comments>https://briancaos.wordpress.com/2024/11/14/convert-json-arrays-into-batches-of-json-arrays-using-the-linq-chunk-method/#respond</comments>
		
		<dc:creator><![CDATA[briancaos]]></dc:creator>
		<pubDate>Thu, 14 Nov 2024 09:50:25 +0000</pubDate>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[.NET Core]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[General .NET]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Array]]></category>
		<category><![CDATA[Batch]]></category>
		<category><![CDATA[Chunk]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">http://briancaos.wordpress.com/?p=3961</guid>

					<description><![CDATA[This is one way of converting a JSON array of any JSON objects into batches. This function uses the LINQ Chunk method to convert a 1 dimensional array input into a 2 dimensional array output: THE CODE: When using the &#8230; <a href="https://briancaos.wordpress.com/2024/11/14/convert-json-arrays-into-batches-of-json-arrays-using-the-linq-chunk-method/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">This is one way of converting a JSON array of any JSON objects into batches. This function uses the <a href="https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.chunk?view=net-8.0" target="_blank" rel="noreferrer noopener">LINQ Chunk</a> method to convert a 1 dimensional array input into a 2 dimensional array output:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
Example input array:

&#91;
    { "a": "1" },
    { "a": "2" },
    { "a": "3" },
    { "a": "4" },
    { "a": "5" },
    { "a": "6" },
    { "a": "7" }
]

Converted into batches of 3:

&#91;
    &#91;
        {"a":"1"},
        {"a":"2"},
        {"a":"3"}
    ],
    &#91;
        {"a":"4"},
        {"a":"5"},
        {"a":"6"}
    ],
    &#91;
        {"a":"7"}
    ]
]
</pre></div>


<p class="wp-block-paragraph"><strong>THE CODE:</strong></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: csharp; highlight: [11,12,13,14,15]; title: ; notranslate">
using System;
using System.Collections.Generic;
using System.Linq;

// For demo purpose: Grab a Json array and convert it into an array of objects
string jsonInputString = &quot;&#91; { \&quot;a\&quot;: \&quot;1\&quot; }, { \&quot;a\&quot;: \&quot;2\&quot; }, { \&quot;a\&quot;: \&quot;3\&quot; }, { \&quot;a\&quot;: \&quot;4\&quot; }, { \&quot;a\&quot;: \&quot;5\&quot; }, { \&quot;a\&quot;: \&quot;6\&quot; }, { \&quot;a\&quot;: \&quot;7\&quot; } ]&quot;;
List&lt;object&gt; jsonInput = System.Text.Json.JsonSerializer.Deserialize&lt;List&lt;object&gt;&gt;(jsonInputString);

// Create a new list of objects, and use the Chunk method to create batches
// of a certain size
List&lt;object&gt; batch = new List&lt;object&gt;();
foreach (var chunk in jsonInput.Chunk(3))
{
  batch.Add(chunk);
}

// For demo purposes, convert the batched objects as a Json string
string jsonOutputString = System.Text.Json.JsonSerializer.Serialize(batch);

// Output the contents
Console.WriteLine(jsonOutputString);
</pre></div>


<p class="wp-block-paragraph">When using the Chunk method, C# does the heavy lifting of breaking the array into batches of a maximum size.</p>



<p class="wp-block-paragraph"><strong>MORE TO READ:</strong></p>



<ul class="wp-block-list">
<li><a href="https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.chunk?view=net-8.0" target="_blank" rel="noreferrer noopener">Enumerable.Chunk&lt;TSource&gt;(IEnumerable&lt;TSource&gt;, Int32)</a> Method from Microsoft</li>



<li><a href="https://www.c-sharpcorner.com/article/streamlining-collection-chunking-in-net-6-chunk-vs-methods/" target="_blank" rel="noreferrer noopener">Streamlining Collection Chunking in .NET 6: .Chunk vs. Methods</a> by <a href="https://www.c-sharpcorner.com/members/jeet-m3" target="_blank" rel="noreferrer noopener">Jitendra Mesavaniya</a></li>



<li><a href="https://briancaos.wordpress.com/2024/08/05/c-sort-jarray-newtonsoft-json/" target="_blank" rel="noreferrer noopener">C# Sort JArray NewtonSoft.Json</a> from briancaos</li>



<li><a href="https://briancaos.wordpress.com/2023/04/28/c-use-httpclient-to-get-json-from-api-endpoint/" target="_blank" rel="noreferrer noopener">C# Use HttpClient to GET JSON from API endpoint</a> from briancaos</li>



<li><a href="https://briancaos.wordpress.com/2019/08/28/httpclient-post-or-put-json-with-content-type-application-json/" target="_blank" rel="noreferrer noopener">C# HttpClient POST or PUT Json with content type application/json</a> from briancaos</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://briancaos.wordpress.com/2024/11/14/convert-json-arrays-into-batches-of-json-arrays-using-the-linq-chunk-method/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3961</post-id>
		<media:content medium="image" url="https://2.gravatar.com/avatar/b1cd26d13baf270ccbc554e8071367bfe693798598bb33f3784394cfde1e1537?s=96&amp;d=https%3A%2F%2F2.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96">
			<media:title type="html">briancaos</media:title>
		</media:content>
	</item>
	</channel>
</rss>