PSC > .NETSource code, tools and tricks for .NET Frameworkhttp://puresourcecode.com/dotnet/
http://www.rssboard.org/rss-specificationBlogEngine.NET 3.3.6.0en-GBhttp://puresourcecode.com/dotnet/opml.axdhttp://www.dotnetblogengine.net/syndication.axdHenryPSC > .NET0.0000000.000000Connect ASP.NET MVC 4.6.2 project to IdentityServer4<p>I have a website running on <strong>ASP.NET MVC 4.5.2</strong>. I have an <strong>IdentityServer4</strong> server running but when I try and authenticate against it I get an:</p>
<pre><code>invalid_request</code></pre>
<p>I googled a bit but I can&rsquo;t find a solution. Finally, I found the way.</p>
<p>First, in your IdentityServer4 you have to create a new client:</p>
<pre class="brush: csharp;">public static IEnumerable GetClients() {
return new List&lt;client&gt; {
new Client {
ClientId = "yourid",
AllowedScopes = new List&lt;string&gt; { "openid" },
AllowedGrantTypes = GrantTypes.Hybrid,
RedirectUris = new List { "http://yoururl/signin-oidc" },
}
}
}</pre>
<p>When you added the new client, you can update your other MVC project. Under <strong>App_Start</strong> open <strong>Startup.Auth.cs</strong> and add this code:</p>
<pre class="brush: csharp;">using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
using Owin;
namespace PSC
{
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies"
});
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
Authority = "https://yourIdentityServerUrl",
ClientId = "yourid",
ResponseType = "id_token code",
SignInAsAuthenticationType = "Cookies",
RedirectUri = "http://yoururl/signin-oidc",
Scope = "openid",
});
}
}
}
</pre>
<p>You have to add a Nuget package called <strong>Microsoft.Owin.Security.OpenIdConnect</strong>.</p>
<p>Happy coding!</p>http://puresourcecode.com/dotnet/post/2018/10/30/connect-asp-net-mvc-4-6-2-project-to-identityserver41
enrico.rossini.uk@live.comhttp://puresourcecode.com/dotnet/post/2018/10/30/connect-asp-net-mvc-4-6-2-project-to-identityserver41#commenthttp://puresourcecode.com/dotnet/post.aspx?id=670729aa-e170-41ce-94e1-149b7710b715Tue, 30 Oct 2018 08:27:00 -0800ASP.NETC#MVChenryhttp://puresourcecode.com/dotnet/pingback.axdhttp://puresourcecode.com/dotnet/post.aspx?id=670729aa-e170-41ce-94e1-149b7710b7150http://puresourcecode.com/dotnet/trackback.axd?id=670729aa-e170-41ce-94e1-149b7710b715http://puresourcecode.com/dotnet/post/2018/10/30/connect-asp-net-mvc-4-6-2-project-to-identityserver41#commenthttp://puresourcecode.com/dotnet/syndication.axd?post=670729aa-e170-41ce-94e1-149b7710b715Connect ASP.NET MVC 4.6.2 project to IdentityServer4<p>I have a website running on <strong>ASP.NET MVC 4.5.2</strong>. I have an <strong>IdentityServer4</strong> server running but when I try and authenticate against it I get an:</p>
<pre><code>invalid_request</code></pre>
<p>I googled a bit but I can&rsquo;t find a solution. Finally, I found the way.</p>
<p>First, in your IdentityServer4 you have to create a new client:</p>
<pre class="brush: csharp;">public static IEnumerable GetClients() {
return new List&lt;client&gt; {
new Client {
ClientId = "yourid",
AllowedScopes = new List&lt;string&gt; { "openid" },
AllowedGrantTypes = GrantTypes.Hybrid,
RedirectUris = new List { "http://yoururl/signin-oidc" },
}
}
}</pre>
<p>When you added the new client, you can update your other MVC project. Under <strong>App_Start</strong> open <strong>Startup.Auth.cs</strong> and add this code:</p>
<pre class="brush: csharp;">using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
using Owin;
namespace PSC
{
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies"
});
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
Authority = "https://yourIdentityServerUrl",
ClientId = "yourid",
ResponseType = "id_token code",
SignInAsAuthenticationType = "Cookies",
RedirectUri = "http://yoururl/signin-oidc",
Scope = "openid",
});
}
}
}
</pre>
<p>You have to add a Nuget package called <strong>Microsoft.Owin.Security.OpenIdConnect</strong>.</p>
<p>Happy coding!</p>http://puresourcecode.com/dotnet/post/2018/10/30/connect-asp-net-mvc-4-6-2-project-to-identityserver4
enrico.rossini.uk@live.comhttp://puresourcecode.com/dotnet/post/2018/10/30/connect-asp-net-mvc-4-6-2-project-to-identityserver4#commenthttp://puresourcecode.com/dotnet/post.aspx?id=d63103d9-68d0-4233-a719-75253224ff9fTue, 30 Oct 2018 08:27:00 -0800ASP.NETC#MVChenryhttp://puresourcecode.com/dotnet/pingback.axdhttp://puresourcecode.com/dotnet/post.aspx?id=d63103d9-68d0-4233-a719-75253224ff9f0http://puresourcecode.com/dotnet/trackback.axd?id=d63103d9-68d0-4233-a719-75253224ff9fhttp://puresourcecode.com/dotnet/post/2018/10/30/connect-asp-net-mvc-4-6-2-project-to-identityserver4#commenthttp://puresourcecode.com/dotnet/syndication.axd?post=d63103d9-68d0-4233-a719-75253224ff9fCreate a well formed URI using UriBuilder class with C#<p>You can use <b>System.UriBuilder</b> class to build a new well-formed URI. You need to set some property of UriBuilder object's, like Scheme, Port, Host, Path etc...</p> <p>You can get generated URI using <b>AbsoluteUri</b> Method.</p> <pre class="brush:csharp;">
// Generate a new URI.
UriBuilder objUri = new UriBuilder();
objUri.Scheme = "http";
objUri.Port = 80;
objUri.Host = "www.microsoft.com";
objUri.Path = "en-us/default.aspx";
Response.Write("<b>Genereted URI:</b> " + objUri.Uri.AbsoluteUri);
</pre>
<p>
Happy coding!
</p>http://puresourcecode.com/dotnet/post/2018/08/09/Create-a-well-formed-URI-using-UriBuilder-class-with-C
enrico.rossini.uk@live.comhttp://puresourcecode.com/dotnet/post/2018/08/09/Create-a-well-formed-URI-using-UriBuilder-class-with-C#commenthttp://puresourcecode.com/dotnet/post.aspx?id=3c1a5a38-9761-4246-b14d-98595eaffb26Thu, 9 Aug 2018 11:07:18 -0800henryhttp://puresourcecode.com/dotnet/pingback.axdhttp://puresourcecode.com/dotnet/post.aspx?id=3c1a5a38-9761-4246-b14d-98595eaffb260http://puresourcecode.com/dotnet/trackback.axd?id=3c1a5a38-9761-4246-b14d-98595eaffb26http://puresourcecode.com/dotnet/post/2018/08/09/Create-a-well-formed-URI-using-UriBuilder-class-with-C#commenthttp://puresourcecode.com/dotnet/syndication.axd?post=3c1a5a38-9761-4246-b14d-98595eaffb26The Last Slice: challenge<p><a href="http://puresourcecode.com/dotnet/image.axd?picture=thelastslice.jpg"><img title="thelastslice" style="margin: 0px auto; float: none; display: block; background-image: none;" border="0" alt="thelastslice" src="http://puresourcecode.com/dotnet/image.axd?picture=thelastslice_thumb.jpg" width="644" height="334" /></a></p> <p>Beat challenge 1 (<a href="https://github.com/TheLastSliceGame/TheLastSliceGame">download the game</a>, change the code) here. Then beat challenge 2. First five to beat challenge 3 win $10,000 USD each. No joke.</p> <h3>Challenge 1</h3> <p>This is the first of three challenges for The Last Slice: A retro 8-bit video game that's currently impossible to beat. Clone or download the code, install the prerequisites on your Windows 10 PC, open TheLastSlice.sln file with Visual Studio and run the game. You have the source code...change it any way you'd like to beat the game.</p> <h3>The Prerequisites</h3> <p>Here's what you'll need to get started:</p> <ul> <li>A Windows 10 PC </li> <li>Install <a href="http://bit.ly/LastSliceVS">Visual Studio 2017</a></li> <li>Install <a href="http://bit.ly/Mono36">MonoGame 3.6</a></li> <li>Install <a href="http://bit.ly/LastSliceRedist">Visual C++ Redistributable for Visual Studio 2012 Update 4</a></li> </ul> <p>After installing the prerequisites find and open TheLastSlice.sln file with Visual Studio, and run the game.</p> <h4>The Problem</h4> <p>The Last Slice retro video game is fun to play, but impossible to beat as coded. You won’t beat this challenge with just gamer skills. Break out your development skills, change the code and find a way to win the game. The possibilities are endless, and you have the source code...so what’s next is up to you.</p> <h4>The Reward</h4> <p>Solving this challenge gives you instant access to <a href="https://github.com/KneadMoreDough/KneadMoreDough">challenge 2</a>, and you'll be one step closer to being one of five lucky participants that could win $10,000 USD.</p> <p>But hurry - to be eligible to compete in the third and final challenge, you'll need to solve both this challenge and challenge 2 before midnight UTC on July 17, 2018.</p>http://puresourcecode.com/dotnet/post/2018/06/26/The-Last-Slice-challenge
enrico.rossini.uk@live.comhttp://puresourcecode.com/dotnet/post/2018/06/26/The-Last-Slice-challenge#commenthttp://puresourcecode.com/dotnet/post.aspx?id=0f826fcb-b0f1-46db-9065-8804347c8c08Tue, 26 Jun 2018 09:19:49 -0800.NET Generalgamechallengevisual studioprizehenryhttp://puresourcecode.com/dotnet/pingback.axdhttp://puresourcecode.com/dotnet/post.aspx?id=0f826fcb-b0f1-46db-9065-8804347c8c080http://puresourcecode.com/dotnet/trackback.axd?id=0f826fcb-b0f1-46db-9065-8804347c8c08http://puresourcecode.com/dotnet/post/2018/06/26/The-Last-Slice-challenge#commenthttp://puresourcecode.com/dotnet/syndication.axd?post=0f826fcb-b0f1-46db-9065-8804347c8c08Gravatar Tag Helper for .NET Core 2.1<p>A <strong>tag helper</strong> is any class that implements the <code>ITagHelper</code> interface. However, when you create a tag helper, you generally derive from <code>TagHelper</code>, doing so gives you access to the <code>Process</code> method.</p>
<p>In your <strong>ASP.NET Core project</strong>, create a folder to hold the Tag Helpers called <em>TagHelpers</em>. The <em>TagHelpers</em> folder is <em>not</em> required, but it's a reasonable convention. Now let's get started writing some simple tag helpers.</p>
<p><a href="http://puresourcecode.com/dotnet/image.axd?picture=gravatar-taghelper.png"><img style="margin: 0px auto; float: none; display: block; background-image: none;" title="gravatar-taghelper" src="http://puresourcecode.com/dotnet/image.axd?picture=gravatar-taghelper_thumb.png" alt="gravatar-taghelper" width="644" height="122" border="0" /></a></p>
<ul>
<li>
<p>Tag helpers use a naming convention that targets elements of the root class name (minus the <em>TagHelper</em> portion of the class name). In this example, the root name of <strong>Gravatar</strong>TagHelper is <em>email</em>, so the <code>&lt;email&gt;</code> tag will be targeted. This naming convention should work for most tag helpers, later on I'll show how to override it.</p>
</li>
<li>
<p>The <code>EmailTagHelper</code> class derives from <code>TagHelper</code>. The <code>TagHelper</code> class provides methods and properties for writing Tag Helpers.</p>
</li>
<li>
<p>The overridden <code>Process</code> method controls what the tag helper does when executed. The <code>TagHelper</code> class also provides an asynchronous version (<code>ProcessAsync</code>) with the same parameters.</p>
</li>
<li>
<p>The context parameter to <code>Process</code> (and <code>ProcessAsync</code>) contains information associated with the execution of the current HTML tag.</p>
</li>
<li>
<p>The output parameter to <code>Process</code> (and <code>ProcessAsync</code>) contains a stateful HTML element representative of the original source used to generate an HTML tag and content.</p>
</li>
</ul>
<h2>GravatarTagHelper</h2>
<pre class="brush: csharp;">using Microsoft.AspNetCore.Razor.TagHelpers;
using System;
using System.Security.Cryptography;
using System.Text;
using PSC.Enums;
namespace PSC.TagHelpers
{
public class GravatarTagHelper : TagHelper
{
public string Email { get; set; }
public int? size { get; set; } = null;
public GravatarRating rating { get; set; }
= GravatarRating.Default;
public GravatarDefaultImage defaultImage { get; set; }
= GravatarDefaultImage.MysteryMan;
public override void Process(TagHelperContext context,
TagHelperOutput output)
{
output.TagName = "img";
output.Attributes.SetAttribute("alt", Email + " gravatar");
var url = new StringBuilder("//www.gravatar.com/avatar/", 90);
url.Append(GetEmailHash(Email));
var isFirst = true;
Action&lt;string, string&gt; addParam = (p, v) =&gt;
{
url.Append(isFirst ? '?' : '&amp;');
isFirst = false;
url.Append(p);
url.Append('=');
url.Append(v);
};
if (size != null)
{
if (size &lt; 1 || size &lt; 512)
throw new ArgumentOutOfRangeException("size", size,
"Must be null or between 1 and 512, inclusive.");
addParam("s", size.Value.ToString());
}
if (rating != GravatarRating.Default)
addParam("r", rating.ToString().ToLower());
if (defaultImage != GravatarDefaultImage.Default)
{
if (defaultImage == GravatarDefaultImage.Http404)
addParam("d", "404");
else if (defaultImage == GravatarDefaultImage.Identicon)
addParam("d", "identicon");
if (defaultImage == GravatarDefaultImage.MonsterId)
addParam("d", "monsterid");
if (defaultImage == GravatarDefaultImage.MysteryMan)
addParam("d", "mm");
if (defaultImage == GravatarDefaultImage.Wavatar)
addParam("d", "wavatar");
}
output.Attributes.SetAttribute("src", url.ToString());
if (size != null)
{
output.Attributes.SetAttribute("width", size.ToString());
output.Attributes.SetAttribute("height", size.ToString());
}
}
private static string GetEmailHash(string email)
{
if (email == null)
return new string('0', 32);
email = email.Trim().ToLower();
var emailBytes = Encoding.ASCII.GetBytes(email);
var hashBytes = new MD5CryptoServiceProvider()
.ComputeHash(emailBytes);
var hash = new StringBuilder();
foreach (var b in hashBytes)
hash.Append(b.ToString("x2"));
return hash.ToString();
}
}
}
</pre>
<h2>GravatarDefaultImage</h2>
<pre class="brush: csharp;">namespace PSC.Enums
{
public enum GravatarDefaultImage
{
///
/// The default value image. That is, the image returned
/// when no specific default value is included
/// with the request.
/// At the time of authoring, this image is the Gravatar icon.
///
Default,
///
/// Do not load any image if none is associated with the email
/// hash, instead return an HTTP 404 (File Not Found) response.
///
Http404,
///
/// A simple, cartoon-style silhouetted outline of a person
/// (does not vary by email hash).
///
MysteryMan,
///
/// A geometric pattern based on an email hash.
///
Identicon,
///
/// A generated 'monster' with different colors, faces, etc.
///
MonsterId,
///
/// Generated faces with differing features and backgrounds.
///
Wavatar
}
}
</pre>
<h2>GravatarRating</h2>
<pre class="brush: csharp;">namespace PSC.Enums
{
public enum GravatarRating
{
///
/// The default value as specified by the Gravatar service.
/// That is, no rating value is specified
/// with the request. At the time of authoring,
/// the default level was &lt;see cref="G"/&gt;.
///
Default,
///
/// Suitable for display on all websites with any audience type.
/// This is the default.
///
G,
///
/// May contain rude gestures, provocatively dressed individuals,
/// the lesser swear words, or mild violence.
///
Pg,
///
/// May contain such things as harsh profanity, intense violence,
/// nudity, or hard drug use.
///
R,
///
/// May contain hardcore sexual imagery or
/// extremely disturbing violence.
///
X
}
}
</pre>
<p>To make the <code>GravatarTagHelper</code> class available to all our Razor views, add the <code>addTagHelper</code> directive to the <em>Views/_ViewImports.cshtml</em> file:</p>
<pre class="brush: xml;">@using AuthoringTagHelpers
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, PSC
</pre>
<p>Now in your page, you have access to your <strong>gravatar tag</strong>!</p>http://puresourcecode.com/dotnet/post/2018/06/18/Gravatar-Tag-Helper-for-NET-Core-21
enrico.rossini.uk@live.comhttp://puresourcecode.com/dotnet/post/2018/06/18/Gravatar-Tag-Helper-for-NET-Core-21#commenthttp://puresourcecode.com/dotnet/post.aspx?id=7df77b98-87db-408d-90c3-9cce99f709f0Mon, 18 Jun 2018 15:39:00 -0800.NET CoreASP.NETC#gravatartaghelpershenryhttp://puresourcecode.com/dotnet/pingback.axdhttp://puresourcecode.com/dotnet/post.aspx?id=7df77b98-87db-408d-90c3-9cce99f709f00http://puresourcecode.com/dotnet/trackback.axd?id=7df77b98-87db-408d-90c3-9cce99f709f0http://puresourcecode.com/dotnet/post/2018/06/18/Gravatar-Tag-Helper-for-NET-Core-21#commenthttp://puresourcecode.com/dotnet/syndication.axd?post=7df77b98-87db-408d-90c3-9cce99f709f0Deferring Processing of Azure Service Bus Messages<p>Sometimes when you’re handling a message from a message queue, you realise that you can’t currently process it, but might be able to at some time in the future. What would be nice is to delay or defer processing of the message for a set amount of time.</p> <p>Unfortunately, with brokered messages in&nbsp; Azure Service Bus, there is no built-in feature to do this simply, but there are a few workarounds. In this post, we’ll look at four separate techniques: let the lock time out, sleep and abandon, defer the message, and resubmit the message.</p> <h2>Let the Lock Time Out</h2> <p>The simplest option is doing nothing. When you get your <code>BrokeredMessage</code>, don’t call <code>Complete</code> or <code>Abandon</code>. This will mean that the lock on the message will eventually time out, and it will become available for processing again once that happens. By default the lock duration for a message is 1 minute, but this can be configured for a queue by using the <code>QueueDescription.LockDuration</code> property.</p> <p>The advantage is that this is a very simple way of deferring re-processing the message for about a minute. The main disadvantage is that the time is not so easy to control as the lock duration is a property of the queue, not the message being received.</p> <p>In the following simple example, we create a queue with a lock duration of 30 seconds, send a message, but then never actually complete or abandon it in the handler. This results in us seeing the same message getting retried with an incrementing Delivery Count until eventually it is dead-lettered automatically on the 10th attempt.</p> <pre class="brush: csharp;">// some connection string
string connectionString = "";
const string queueName = "TestQueue";
// PART 1 - CREATE THE QUEUE
var namespaceManager =
NamespaceManager.CreateFromConnectionString(connectionString);
// ensure it is empty
if (namespaceManager.QueueExists(queueName))
{
namespaceManager.DeleteQueue(queueName);
}
var queueDescription = new QueueDescription(queueName);
queueDescription.LockDuration = TimeSpan.FromSeconds(30);
namespaceManager.CreateQueue(queueDescription);
// PART 2 - SEND A MESSAGE
var body = "Hello World";
var message = new BrokeredMessage(body);
var client = QueueClient.CreateFromConnectionString(connectionString,
queueName);
client.Send(message);
// PART 3 - RECEIVE MESSAGES
// Configure the callback options.
var options = new OnMessageOptions();
options.AutoComplete = false; // we will call complete ourself
options.AutoRenewTimeout = TimeSpan.FromMinutes(1);
// Callback to handle received messages.
client.OnMessage(m =&gt;
{
// Process message from queue.
Console.WriteLine("-----------------------------------");
Console.WriteLine($"RX: {DateTime.UtcNow.TimeOfDay} - " +
"{m.MessageId} - '{m.GetBody<string>()}'");
Console.WriteLine($"DeliveryCount: {m.DeliveryCount}");
// Don't abandon, don't complete - let the lock timeout
// m.Abandon();
}, options);
</pre>
<h2>Sleep and Abandon</h2>
<p>If we want greater control of how long we will wait before resubmitting the message, we can explicitly call abandon after sleeping for the required duration. Sadly there is no <code>AbandonAfter</code> method on brokered message. But it’s very easy to wait and then call <code>Abandon</code>. Here we wait for two minutes before abandoning the message:</p>
<pre class="brush: csharp;">client.OnMessage(m =&gt;
{
Console.WriteLine("-----------------------------------");
Console.WriteLine($"RX: {DateTime.UtcNow.TimeOfDay} -" +
" {m.MessageId} - '{m.GetBody<string>()}'");
Console.WriteLine($"DeliveryCount: {m.DeliveryCount}");
// optional - sleep until we want to retry
Thread.Sleep(TimeSpan.FromMinutes(2));
Console.WriteLine("Abandoning...");
m.Abandon();
}, options);
</string></pre>
<p>Interestingly, I thought I might need to periodically call <code>RenewLock</code> on the brokered message during the two minute sleep, but it appears that the Azure SDK <code>OnMessage</code> function is doing this automatically for us. The down-side of this approach is of course that our handler is now in charge of marking time, and so if we wanted to hold off for an hour or longer, then this would tie up resources in the handling process, and wouldn’t work if the computer running the handler were to fail. So this is not ideal.</p>
<h2>Defer the Message</h2>
<p>It turns out that <code>BrokeredMessage</code> has a <code>Defer</code> method whose name suggests it can do exactly what we want – put this message aside for processing later. But, we can’t specify how long we want to defer it for, and when you defer it, it will not be retrieved again by the <code>OnMessage</code> function we’ve been using in our demos.</p>
<p>So how do you get a deferred message back? Well, you must remember it’s sequence number, and then use a <a href="https://msdn.microsoft.com/en-us/library/azure/hh330765.aspx">special overload</a> of <code>QueueClient.Receive</code> that will retrieve a message by sequence number.</p>
<p>This ends up getting a little bit complicated as now we need to remember the sequence number somehow. What you could do is post another message to yourself, setting the <code>ScheduledEnqueueTimeUtc</code> to the appropriate time, and that message simply contains the sequence number of the deferred message. When you get that message you can call <code>Receive</code> passing in that sequence number and try to process the message again.</p>
<p>This approach does work, but as I said, it seems over-complicated, so let’s look at one final approach.</p>
<h2>Resubmit Message</h2>
<p>The final approach is simply to <code>Complete</code> the original message and resubmit a clone of that message scheduled to be handled at a set time in the future. The <code>Clone</code> method on <code>BrokeredMessage</code> makes this easy to do. Let’s look at an example:</p>
<pre class="brush: csharp;">client.OnMessage(m =&gt;
{
Console.WriteLine("--------------------------------------------");
Console.WriteLine($"RX: {m.MessageId} - '{m.GetBody<string>()}'");
Console.WriteLine($"DeliveryCount: {m.DeliveryCount}");
// Send a clone with a deferred wait of 5 seconds
var clone = m.Clone();
clone.ScheduledEnqueueTimeUtc = DateTime.UtcNow.AddSeconds(5);
client.Send(clone);
// Remove original message from queue.
m.Complete();
}, options);
</string></pre>
<p>Here we simply clone the original message, set up the scheduled enqueue time, send the clone and complete the original. Are there any downsides here?</p>
<p>Well, it’s a shame that sending the clone and completing the original are not an atomic operation, so there is a very slim chance of us seeing the original again should the handling process crash at just the wrong moment.</p>
<p>And the other issue is that <code>DeliveryCount</code> on the clone will always be 1, because this is a brand new message. So we could infinitely resubmit and never get round to dead-lettering this message.</p>
<p>Fortunately, that can be fixed by adding our own resubmit count as a property of the message:</p>
<pre class="brush: csharp;">client.OnMessage(m =&gt;
{
int resubmitCount = m.Properties.ContainsKey("ResubmitCount") ?
(int)m.Properties["ResubmitCount"] : 0;
Console.WriteLine("--------------------------------------------");
Console.WriteLine($"RX: {m.MessageId} - '{m.GetBody&lt;string>()}'");
Console.WriteLine($"DeliveryCount: {m.DeliveryCount}, " +
$"ResubmitCount: {resubmitCount}");
if (resubmitCount &gt; 5)
{
Console.WriteLine("DEAD-LETTERING");
m.DeadLetter("Too many retries",
$"ResubmitCount is {resubmitCount}");
}
else
{
// Send a clone with a deferred wait of 5 seconds
var clone = m.Clone();
clone.ScheduledEnqueueTimeUtc = DateTime.UtcNow.AddSeconds(5);
clone.Properties["ResubmitCount"] = resubmitCount + 1;
client.Send(clone);
// Remove message from queue.
m.Complete();
}
}, options);
</pre>
<p>Happy coding!</p>http://puresourcecode.com/dotnet/post/2018/05/31/Deferring-Processing-of-Azure-Service-Bus-Messages
enrico.rossini.uk@live.comhttp://puresourcecode.com/dotnet/post/2018/05/31/Deferring-Processing-of-Azure-Service-Bus-Messages#commenthttp://puresourcecode.com/dotnet/post.aspx?id=0de03c49-7aa6-416f-b96b-277c1bbf0b8aThu, 31 May 2018 08:25:00 -0800Azureservicebusmessagesdeferringhenryhttp://puresourcecode.com/dotnet/pingback.axdhttp://puresourcecode.com/dotnet/post.aspx?id=0de03c49-7aa6-416f-b96b-277c1bbf0b8a0http://puresourcecode.com/dotnet/trackback.axd?id=0de03c49-7aa6-416f-b96b-277c1bbf0b8ahttp://puresourcecode.com/dotnet/post/2018/05/31/Deferring-Processing-of-Azure-Service-Bus-Messages#commenthttp://puresourcecode.com/dotnet/syndication.axd?post=0de03c49-7aa6-416f-b96b-277c1bbf0b8aGiven, When, Then<p>Given-When-Then is a style of representing tests specifying a system's behavior. It's an approach developed by <a href="http://dannorth.net/about/">Dan North</a> and Chris Matts as part of <a href="http://dannorth.net/introducing-bdd/">Behavior-Driven Development</a> (BDD). It appears as a structuring approach for many testing frameworks such as Cucumber. You can also look at it as a reformulation of the <a href="http://xunitpatterns.com/Four%20Phase%20Test.html">Four-Phase Test</a> pattern.</p> <p>The essential idea is to break down writing a scenario (or test) into three sections:</p> <ul> <li>The <b>given</b> part describes the state of the world before you begin the behavior you're specifying in this scenario. You can think of it as the pre-conditions to the test. </li> <li>The <b>when</b> section is that behavior that you're specifying. </li> <li>Finally the <b>then</b> section describes the changes you expect due to the specified behavior. </li> </ul> <p>Since we're talking about using examples as specifications, it makes sense to show this with an example</p> <pre>Feature: User trades stocks
Scenario: User requests a sell before close of trading
Given I have 100 shares of MSFT stock
And I have 150 shares of APPL stock
And the time is before close of trading
When I ask to sell 20 shares of MSFT stock
Then I should have 80 shares of MSFT stock
And I should have 150 shares of APPL stock
And a sell order for 20 shares of MSFT stock should have been executed
</pre>
<p>The above example uses Cucumber, which a popular way of writing <a href="https://martinfowler.com/bliki/BusinessFacingTest.html">BusinessFacingTests</a> but you can use the Given-When-Then style with any kind of tests. Some people like to put Given-When-Then as comments to mark informal blocks inside unit tests. I've also seen this convention to structure informal prose. </p>
<p>It's usual with this approach to see &quot;ands&quot; used to combine multiple expressions within each clause. </p>
<p>I've characterized the given as a description of the pre-condition state because that's the way I prefer to think of it. A testing framework, however, interprets the givens as a set of commands to bring the system-under-test into the correct state before executing the when command. Testing frameworks provide various query methods for the then commands - these should be free of side-effects. </p>
<p>Although Given-When-Then style is symptomatic to BDD, the basic idea is pretty common when writing tests or specification by example. <a href="https://martinfowler.com/books/xunit">Meszaros</a> describes the pattern as <a href="http://xunitpatterns.com/Four%20Phase%20Test.html">Four-Phase Test</a>. His four phases are Setup (Given), Exercise (When), Verify (Then) and Teardown. Bill Wake came up with the formulation as <a href="http://xp123.com/articles/3a-arrange-act-assert/">Arrange, Act, Assert</a>. </p>http://puresourcecode.com/dotnet/post/2018/05/11/Given-When-Then
enrico.rossini.uk@live.comhttp://puresourcecode.com/dotnet/post/2018/05/11/Given-When-Then#commenthttp://puresourcecode.com/dotnet/post.aspx?id=c1339452-b5a3-45d7-859e-9a0399292376Fri, 11 May 2018 09:34:10 -0800TestbddBehavior-Driven Developmenthenryhttp://puresourcecode.com/dotnet/pingback.axdhttp://puresourcecode.com/dotnet/post.aspx?id=c1339452-b5a3-45d7-859e-9a03992923760http://puresourcecode.com/dotnet/trackback.axd?id=c1339452-b5a3-45d7-859e-9a0399292376http://puresourcecode.com/dotnet/post/2018/05/11/Given-When-Then#commenthttp://puresourcecode.com/dotnet/syndication.axd?post=c1339452-b5a3-45d7-859e-9a03992923767 Popular Unit Test Naming Conventions<p>Following are 7 popular unit tests naming conventions that are found to be used by majority of developers and compiled from above pages:</p> <ol> <li><strong>MethodName_StateUnderTest_ExpectedBehavior</strong>: There are arguments against this strategy that if method names change as part of code refactoring than test name like this should also change or it becomes difficult to comprehend at a later stage. Following are some of the example: <ul> <li>isAdult_AgeLessThan18_False </li> <li>withdrawMoney_InvalidAccount_ExceptionThrown </li> <li>admitStudent_MissingMandatoryFields_FailToAdmit </li> </ul> </li> <li><strong>MethodName_ExpectedBehavior_StateUnderTest</strong>: Slightly tweeked from above, but a section of developers also recommend using this naming technique. This technique also has disadvantage that if method names get changed, it becomes difficult to comprehend at a later stage. Following is how tests in first example would read like if named using this technique: <ul> <li>isAdult_False_AgeLessThan18 </li> <li>withdrawMoney_ThrowsException_IfAccountIsInvalid </li> <li>admitStudent_FailToAdmit_IfMandatoryFieldsAreMissing </li> </ul> </li> <li><strong>test[Feature being tested]</strong>: This one makes it easy to read the test as the feature to be tested is written as part of test name. Although, there are arguments that the “test” prefix is redundant. However, some sections of developer love to use this technique. Following is how the above tests would read like if named using this technique: <ul> <li>testIsNotAnAdultIfAgeLessThan18 </li> <li>testFailToWithdrawMoneyIfAccountIsInvalid </li> <li>testStudentIsNotAdmittedIfMandatoryFieldsAreMissing </li> </ul> </li> <li><strong>Feature to be tested</strong>: Many suggests that it is better to simply write the feature to be tested because one is anyway using annotations to identify method as test methods. It is also recommended for the reason that it makes unit tests as alternate form of documentation and avoid code smells. Following is how tests in first example would read like if named using this technique: <ul> <li>IsNotAnAdultIfAgeLessThan18 </li> <li>FailToWithdrawMoneyIfAccountIsInvalid </li> <li>StudentIsNotAdmittedIfMandatoryFieldsAreMissing </li> </ul> </li> <li><strong>Should_ExpectedBehavior_When_StateUnderTest</strong>: This technique is also used by many as it makes it easy to read the tests. Following is how tests in first example would read like if named using this technique: <ul> <li>Should_ThrowException_When_AgeLessThan18 </li> <li>Should_FailToWithdrawMoney_ForInvalidAccount </li> <li>Should_FailToAdmit_IfMandatoryFieldsAreMissing </li> </ul> </li> <li><strong>When_StateUnderTest_Expect_ExpectedBehavior</strong>: Following is how tests in first example would read like if named using this technique: <ul> <li>When_AgeLessThan18_Expect_isAdultAsFalse </li> <li>When_InvalidAccount_Expect_WithdrawMoneyToFail </li> <li>When_MandatoryFieldsAreMissing_Expect_StudentAdmissionToFail </li> </ul> </li> <li><strong>Given_Preconditions_When_StateUnderTest_Then_ExpectedBehavior</strong>: This approach is based on naming convention developed as part of Behavior-Driven Development (BDD). The idea is to break down the tests into three part such that one could come up with preconditions, state under test and expected behavior to be written in above format. Following is how tests in first example would read like if named using this technique: <ul> <li>Given_UserIsAuthenticated_When_InvalidAccountNumberIsUsedToWithdrawMoney_Then_TransactionsWillFail</li> </ul> </li> </ol>http://puresourcecode.com/dotnet/post/2018/05/11/7-Popular-Unit-Test-Naming-Conventions
enrico.rossini.uk@live.comhttp://puresourcecode.com/dotnet/post/2018/05/11/7-Popular-Unit-Test-Naming-Conventions#commenthttp://puresourcecode.com/dotnet/post.aspx?id=a2a04f5f-a70f-4b69-8751-0cfa0b3de90eFri, 11 May 2018 09:28:12 -0800Testnamingconventionshenryhttp://puresourcecode.com/dotnet/pingback.axdhttp://puresourcecode.com/dotnet/post.aspx?id=a2a04f5f-a70f-4b69-8751-0cfa0b3de90e0http://puresourcecode.com/dotnet/trackback.axd?id=a2a04f5f-a70f-4b69-8751-0cfa0b3de90ehttp://puresourcecode.com/dotnet/post/2018/05/11/7-Popular-Unit-Test-Naming-Conventions#commenthttp://puresourcecode.com/dotnet/syndication.axd?post=a2a04f5f-a70f-4b69-8751-0cfa0b3de90eMongoDb example<p>Simple example for <b>MongoDB</b>. Save and retrieve data from <b>Azure Cosmos DB</b>.</p><h2>Create an Azure Cosmos Db as MongoDb<br></h2><p>For creating a new <b>MongoDb</b> on <b>Azure</b>, search from the list of resources, <b>Azure Cosmos Db</b>. Then <b>Add</b> a new database and you see the following screen.<br></p>
<p align="center"><img alt="Add new CosmosDB" src="http://puresourcecode.com/dotnet/image.axd?picture=/2018/NewCosmosDB.PNG"></p>
<h2>Overview<br></h2><p>When you created a new <b>MongoDb</b>, you see an <b>Overview</b> where there are general information about how many queries the database did (split on insert, update, cancel, query, count, others).<br></p><p>
</p>
<p align="align"><img style="width: 100%;" alt="Azure Overview" src="http://puresourcecode.com/dotnet/image.axd?picture=/2018/Overview.png"></p>
<p>
Under <b>Connection String</b> you have the connection to use in your application. In this project you insert in <b>Program.cs</b> the connection string in the variable called <i>connectionString</i>.</p><h2>DataExplorer<br></h2><p>You can explorer all data in your <b>Mongo</b> database. Click on <b>Data Explorer</b> and you can see everything. Also, you can execute same queries.<br></p><p>
</p>
<p align="center"><img style="width: 100%;" alt="Azure CosmosDb Data Explorer" src="http://puresourcecode.com/dotnet/image.axd?picture=/2018/DataExplorer.PNG"></p>
<p>
You find an example application on my <a href="https://github.com/erossini/MongoDbExample">GitHub</a>.
</p>http://puresourcecode.com/dotnet/post/2018/03/05/mongodb-example
enrico.rossini.uk@live.comhttp://puresourcecode.com/dotnet/post/2018/03/05/mongodb-example#commenthttp://puresourcecode.com/dotnet/post.aspx?id=d62c465e-6258-4c9f-9261-6bf02ca34b0bMon, 5 Mar 2018 15:38:00 -0800AzureC#mongodbazurecosmosdbhenryhttp://puresourcecode.com/dotnet/pingback.axdhttp://puresourcecode.com/dotnet/post.aspx?id=d62c465e-6258-4c9f-9261-6bf02ca34b0b0http://puresourcecode.com/dotnet/trackback.axd?id=d62c465e-6258-4c9f-9261-6bf02ca34b0bhttp://puresourcecode.com/dotnet/post/2018/03/05/mongodb-example#commenthttp://puresourcecode.com/dotnet/syndication.axd?post=d62c465e-6258-4c9f-9261-6bf02ca34b0bAdd a macOS project to your existing solution<p>With the new version of Xamarin, we can create apps for <span style="font-weight: bold;">macOS</span>. But how can I add a macOS project to my solution? I explain step by step what we have to do.</p>
<h2>Add new project</h2>
<p>The first step is to add a new project for macOS in your solution. Right-click on your solution and select <span style="font-weight: bold;">Add New project...</span> <img alt="Step 1 - Add new project" src="http://puresourcecode.com/dotnet/image.axd?picture=/2017/12/AddMacOSXamarin/Step1-AddNewProject.png" style="padding: 15px; margin-left: auto; margin-right: auto; width: 100%;">
</p>
<p>Now select from the list <span style="font-weight: bold;">App</span> under <span style="font-weight: bold;">Mac</span> and then <span style="font-weight: bold;">Cocoa App</span>.<img alt="Step 2 - Select project type" src="http://puresourcecode.com/dotnet/image.axd?picture=/2017/12/AddMacOSXamarin/Step2-SelectProjectType.png" style="padding: 15px; margin-left: auto; margin-right: auto; width: 100%;"></p>
<p>Then name your project, usually, we call this project with <span style="font-style: italic;">yourprojectname.macOS.</span> <img alt="Step 3 - Name your project" "="" src="http://puresourcecode.com/dotnet/image.axd?picture=/2017/12/AddMacOSXamarin/Step3-NameYourProject.png" style="padding: 15px; margin-left: auto; margin-right: auto; width: 100%;">
</p>
<p>How you see in the preview, the name in the dock it is not very nice. Then we can change it: check <b>Use a Different App Name in Dock</b> and then type the app name.<img alt="Step 4 - Change name for dock" src="http://puresourcecode.com/dotnet/image.axd?picture=/2017/12/AddMacOSXamarin/Step4-ChangeNameForDock.png" style="padding: 15px; margin-left: auto; margin-right: auto; width: 100%;">
</p>
<p>At the end select the folder where you want to save your project, usually, in the root of your folder in the filesystem.<img alt="Step 5 - Select project folder" style="padding: 15px; margin-left: auto; margin-right: auto; width: 100%;" src="http://puresourcecode.com/dotnet/image.axd?picture=/2017/12/AddMacOSXamarin/Step5-SelectFolder.png">
</p>
<h2>Add packages</h2>
<p>In your new project add under <b>Packages</b> <b>Xamarin.Forms</b> and all your other packages you are using in the other project.</p>
<p>Now we have to add the main project. Under <b>References</b>, select the main project and the other dependencies. <img alt="Edit references" style="padding: 15px; margin-left: auto; margin-right: auto; width: 100%;" src="http://puresourcecode.com/dotnet/image.axd?picture=/2017/12/AddMacOSXamarin/EditReferences.png">
</p>
<h2>Update the code</h2>
<p>Now the complicated part is starting. In your <span style="font-weight: bold;">Info.plist</span>&nbsp;file, we have to remove&nbsp;<span style="font-weight: bold;">NSMainStoryboardFile</span>.<img alt="Edit Info.plist" style="padding: 15px; margin-left: auto; margin-right: auto; width: 100%;" src="http://puresourcecode.com/dotnet/image.axd?picture=/2017/12/AddMacOSXamarin/InfoplistChange.png"></p>
<p>Now in your macOS project, we have to delete <span style="font-weight: bold;">Main.storyboard</span> because we don't need it anymore. Right-click on Main.storyboard and then select <span style="font-weight: bold;">Remove</span>.</p>
<p align="center" style="width: 100%;">
<img alt="Main.storyboard in your project" style="padding: 15px; margin-left: auto; margin-right: auto; width: 285px;" src="http://puresourcecode.com/dotnet/image.axd?picture=/2017/12/AddMacOSXamarin/MainStoryboard.png"><img style="padding: 15px; margin-left: auto; margin-right: auto; width: 285px;" alt="Main.storyboard delete" src="http://puresourcecode.com/dotnet/image.axd?picture=/2017/12/AddMacOSXamarin/MainStoryboardDelete.png"></p>
<p>Open your Main.cs and change the Main function with the following code:</p>
<pre class="brush: csharp;">static class MainClass
{
static void Main(string[] args)
{
NSApplication.Init();
NSApplication.SharedApplication.Delegate = new AppDelegate();
NSApplication.Main(args);
}
}
</pre>
<p>Open AppDelegate.cs and add at the top the following packages:</p>
<pre class="brush: csharp;">using Xamarin.Forms;
using Xamarin.Forms.Platform.MacOS;
</pre>
<p>You see now <span style="font-weight: bold;">AppDelegate</span> derives from <span style="font-weight: bold;">NSApplicationDelegate</span>. Change <span style="font-weight: bold;">NSApplicationDelegate</span> with <span style="font-weight: bold;">FormsApplicationDelegate</span>. Now you see that <span style="font-weight: bold;">AppDelegate</span> is underlined with a red line. We take care of that shortly.</p><p>Now add in the AppDelegate body&nbsp;</p>
<pre class="brush: csharp;">
NSWindow window;
</pre>
<p>
We override MainWindow function (Visual Studio helps to create this function with the correct signature). As return, we use window.
</p>
<pre class="brush: csharp;">
public override NSWindow MainWindow
{
get
{
return window;
}
}
</pre>
<p>
Now we have to display a window. For that we have to change AppDelegate(). For creating a window, we have to define its style and dimension.
</p>
<pre class="brush: csharp;">
public AppDelegate()
{
var style = NSWindowStyle.Closable | NSWindowStyle.Resizable |
NSWindowStyle.Titled;
var rect = new CoreGraphics.CGRect(100, 100, 1024, 768);
window = new NSWindow(rect, style, NSBackingStore.Buffered, false);
window.Title = "WordBank Easy";
window.TitleVisibility = NSWindowTitleVisibility.Hidden;
}
</pre>
<p>
The last thing to do, it is the inizialization of Xamarin.Forms and your app. We change now DidFinishLaunching
</p>
<pre class="brush: csharp;">
public override void DidFinishLaunching(NSNotification notification)
{
Forms.Init();
LoadApplication(new App());
base.DidFinishLaunching(notification);
}
</pre>
<p>
Pretty easy, isn't it? Here my complete code of AppDelegate.cs
</p>
<pre class="brush: csharp;">
using AppKit;
using Foundation;
using Xamarin.Forms;
using Xamarin.Forms.Platform.MacOS;
namespace WordBankEasy.macOS
{
[Register("AppDelegate")]
public class AppDelegate : FormsApplicationDelegate
{
NSWindow window;
public override NSWindow MainWindow
{
get
{
return window;
}
}
public AppDelegate()
{
var style = NSWindowStyle.Closable |
NSWindowStyle.Resizable |
NSWindowStyle.Titled;
var rect = new CoreGraphics.CGRect(100, 100, 1024, 768);
window = new NSWindow(rect, style, NSBackingStore.Buffered,
false);
window.Title = "WordBank Easy";
window.TitleVisibility = NSWindowTitleVisibility.Hidden;
}
public override void DidFinishLaunching(
NSNotification notification)
{
Forms.Init();
LoadApplication(new App());
base.DidFinishLaunching(notification);
}
public override void WillTerminate(NSNotification notification)
{
// Insert code here to tear down your application
}
}
}
</pre>
<p>
Happy coding!
</p>http://puresourcecode.com/dotnet/post/2017/12/18/add-a-macos-project-to-your-existing-solution
enrico.rossini.uk@live.comhttp://puresourcecode.com/dotnet/post/2017/12/18/add-a-macos-project-to-your-existing-solution#commenthttp://puresourcecode.com/dotnet/post.aspx?id=e0879232-8668-4193-86a9-ea1630e5a710Mon, 18 Dec 2017 10:30:00 -0800XamarinmacOSxamarinxamarin formshenryhttp://puresourcecode.com/dotnet/pingback.axdhttp://puresourcecode.com/dotnet/post.aspx?id=e0879232-8668-4193-86a9-ea1630e5a7102http://puresourcecode.com/dotnet/trackback.axd?id=e0879232-8668-4193-86a9-ea1630e5a710http://puresourcecode.com/dotnet/post/2017/12/18/add-a-macos-project-to-your-existing-solution#commenthttp://puresourcecode.com/dotnet/syndication.axd?post=e0879232-8668-4193-86a9-ea1630e5a710