When setting up your Azure App ID for your web apps, it's extremely important that you follow the recommended format of "https://<your tenant name>/<your app name>"
Otherwise, delegated authentication will NOT work!!
Thursday, August 27, 2015
Wednesday, August 26, 2015
Using ADAL in Javascript to enable use of Azure Active Directory from an AngularJS SPA
Check this out, apparently it came out last fall in Azure:
http://www.cloudidentity.com/blog/2014/10/28/adal-javascript-and-angularjs-deep-dive/
http://www.cloudidentity.com/blog/2014/10/28/adal-javascript-and-angularjs-deep-dive/
Enabling group membership claims in delegated tokens in Azure Active Directory
In your application manifest, add the following to the root object:
{
....
"groupMembershipClaims": "All",
....
}
{
....
"groupMembershipClaims": "All",
....
}
Fixing redirect loops in Azure web apps that use Azure Active Directory for authentication
We've recently been using Azure Active Directory to handle authentication for a bunch of our Line-Of-Business applications that we're moving into the cloud. Unfortunately, we've been noticing that in some circumstances, we encounter redirect loops that the browser can't break out of and I've been scratching my head over it. As it turns out, the loops had a common cause: going to a URL in the application that started with http://.
Since we're all good programmers here ;), we always want to be using best practices and enforcing secure connections anyway, but it also turned out to be the fix: adding [RequireHttps] to the top of our filters list in FilterConfig.cs solved the problem and closed a security hole at the same time.
As for the initial cause: why would anybody be using HTTP anyway ? It turns out that HTTP is the default scheme for URLs in the Azure portal when you're viewing the settings for an application and people were clicking on those links to go straight into the app.
Alex
Since we're all good programmers here ;), we always want to be using best practices and enforcing secure connections anyway, but it also turned out to be the fix: adding [RequireHttps] to the top of our filters list in FilterConfig.cs solved the problem and closed a security hole at the same time.
As for the initial cause: why would anybody be using HTTP anyway ? It turns out that HTTP is the default scheme for URLs in the Azure portal when you're viewing the settings for an application and people were clicking on those links to go straight into the app.
Alex
Labels:
aad,
active,
authentication,
authorization,
azure,
directory,
loop,
loops,
redirect
Tuesday, August 25, 2015
Parameterizing ApplicationInsights.config
I've been working on a lot of web applications in Azure recently, and we're using Application Insights to analyze logs and instrument events in the application. Additionally, we're using MSDeploy to deploy all of our applications as we're trying to get to the point of having Continuous Delivery on-premise. Because we use multiple environments, we need to use the parameters.xml file and SetParameters files to set parameters at deployment time, meaning that we also need to parameterize the InstrumentationKey used by Application Insights to determine which instance of App Insights gets the instrumentation for which application.
This is a bit of a challenge because the XPath support for the parameters.xml file is incomplete and leaves something to be desired. At first glance, I tried to use the naive XPath expression to parameterize our InstrumentationKey:
Match="/ApplicationInsights/InstrumentationKey"
I realized that this wasn't working after checking our deployments, so after some Googling, I found the recommendation that to parameterize an *element* rather than an attribute, you need to use "/text()" in your XPath expression (which makes sense if you know enough about XPath and XQuery). So I tried it:
Match="/ApplicationInsights/InstrumentationKey/text()"
Still didn't work. Then I was stumped for a while and let things simmer.
After a couple more hours and getting frustrated, it hit me: when parameterizing another element a few weeks prior, I ran into issues because a parent element of the one that I wanted to parameterize overrode the default namespace. I checked the ApplicationInsights.config file, and sure enough, the default namespace was the non-empty namespace. I had to use a wildcard to solve the previous problem, so I tried the following:
Match="/*/InstrumentationKey/text()"
Still didn't work, much to my surprise this time. After a little bit more Googling around, I found out that this time it was because the *root* element itself used a non-empty namespace, and overrode the default. I stumbled across this response by Vishal Joshi to a comment on one of his blog posts, which included a suggestion for it using something I didn't even know you could do with XPath (and I've actually got quite a bit of experience using XPath): use the local-name query operator to match only on local name rather than fully qualified name. If you're querying a document that uses an empty default namespace, they're both the same, hence why the simple match expressions work 99% of the time. Updating my query to this:
Match="//*[local-name()='InstrumentationKey']/text()"
... worked like a charm!
This is a bit of a challenge because the XPath support for the parameters.xml file is incomplete and leaves something to be desired. At first glance, I tried to use the naive XPath expression to parameterize our InstrumentationKey:
Match="/ApplicationInsights/InstrumentationKey"
I realized that this wasn't working after checking our deployments, so after some Googling, I found the recommendation that to parameterize an *element* rather than an attribute, you need to use "/text()" in your XPath expression (which makes sense if you know enough about XPath and XQuery). So I tried it:
Match="/ApplicationInsights/InstrumentationKey/text()"
Still didn't work. Then I was stumped for a while and let things simmer.
After a couple more hours and getting frustrated, it hit me: when parameterizing another element a few weeks prior, I ran into issues because a parent element of the one that I wanted to parameterize overrode the default namespace. I checked the ApplicationInsights.config file, and sure enough, the default namespace was the non-empty namespace. I had to use a wildcard to solve the previous problem, so I tried the following:
Match="/*/InstrumentationKey/text()"
Still didn't work, much to my surprise this time. After a little bit more Googling around, I found out that this time it was because the *root* element itself used a non-empty namespace, and overrode the default. I stumbled across this response by Vishal Joshi to a comment on one of his blog posts, which included a suggestion for it using something I didn't even know you could do with XPath (and I've actually got quite a bit of experience using XPath): use the local-name query operator to match only on local name rather than fully qualified name. If you're querying a document that uses an empty default namespace, they're both the same, hence why the simple match expressions work 99% of the time. Updating my query to this:
Match="//*[local-name()='InstrumentationKey']/text()"
... worked like a charm!
Creating users in a SQL Azure database
... is not as straight forward as you would think. It has some slightly different requirements for syntax than what you'd normally use to create users in a local or on-premise SQL Server instance.
You can see the tutorial page on MSDN here.
You can see the tutorial page on MSDN here.
Thursday, August 20, 2015
Logging your application with App Insights instead of Windows Azure Diagnostics
We've recently started deploying applications to Microsoft Azure. Unfortunately, we don't use Cloud Apps for our web apps, and instead use MSDeploy on the command line to enable automated deployment. Consequently, we don't have any .csdef files in which to implement Windows Azure Diagnostics (WAD).
Fortunately, there's a suitable replacement for applications in Azure App Service (rather than Cloud Services): Application Insights. Not only does this provide a TraceListener for tracing your application, but also provides a whole suite of other useful diagnostics, making this something that you should really be using anyway. Using the links here and here, I was able to get up to speed with App Insights within an hour and a half, and implement a working solution for our application.
Fortunately, there's a suitable replacement for applications in Azure App Service (rather than Cloud Services): Application Insights. Not only does this provide a TraceListener for tracing your application, but also provides a whole suite of other useful diagnostics, making this something that you should really be using anyway. Using the links here and here, I was able to get up to speed with App Insights within an hour and a half, and implement a working solution for our application.
Wednesday, August 19, 2015
Using the Azure Key Vault: an experiment
So, I've found this article on MSDN about how to use the Azure Key Vault for storing secrets, e.g. encryption keys. Let's see how it goes.
**UPDATE** : So, apparently we won't be able to use the Key Vault because use of the key vault at this time requires that your application be used in conjunction with Azure Active Directory, which ours does not. That's unfortunate.
**UPDATE** : So, apparently we won't be able to use the Key Vault because use of the key vault at this time requires that your application be used in conjunction with Azure Active Directory, which ours does not. That's unfortunate.
Labels:
azure,
encryption,
initialization,
key,
vault,
vector
A really quick note about deploying SQL Server .dacpac files to SQL Azure
When you're using SqlPackage.exe to deploy a .dacpac to Azure, you must have access to the 'master' table in order for the tool to retrieve information necessary to create a diff of the database and deploy the differences during the Publish action.
For that reason, you need the 'sa' account, because simply having 'db_owner' on the Azure database is not sufficient.
For that reason, you need the 'sa' account, because simply having 'db_owner' on the Azure database is not sufficient.
Labels:
azure,
dacpac,
deploy,
deployment,
server,
sql,
sqlpackage
Tuesday, August 18, 2015
Debugging database deployments with MSDeploy and SqlPackage
I recently had problems deploying a database to Azure, and thanks to this article, I now know why. The best part of this experience is that I've learned to debug this in a much easier manner than relying on the unhelpful error message:
*** An error occurred during deployment plan generation. Deployment cannot continue.
Failed to import target model my-database-name. Detailed message Value cannot be null.
Parameter name: conn
Value cannot be null.
Parameter name: conn
The short of it is that:
1) you need to enable a log trace with these commands for dbDacFx and SSDT:
logman create trace -n DacFxDebug -p "Microsoft-SQLServerDataTools" 0x800 -o "%LOCALAPPDATA%\DacFxDebug.etl" -ets
logman create trace -n SSDTDebug -p "Microsoft-SQLServerDataToolsVS" 0x800 -o "%LOCALAPPDATA%\SSDTDebug.etl" -ets
2) Go execute the command that's causing you grief
3) Execute the following commands to stop the logging trace:
logman stop DacFxDebug -ets
logman stop SSDTDebug -ets
4) Open 'eventvwr' in the Run dialog available from the Start Menu
5) Go to the right side 'Actions' pane, and click on 'Open Saved Log'.
6) When prompted to convert the log, click 'No'.
The logs will display under the 'Saved Logs' folder in the left hand navigation tree, and you'll be able to inspect the errors that occurred. Good luck with deployment!
*** An error occurred during deployment plan generation. Deployment cannot continue.
Failed to import target model my-database-name. Detailed message Value cannot be null.
Parameter name: conn
Value cannot be null.
Parameter name: conn
The short of it is that:
1) you need to enable a log trace with these commands for dbDacFx and SSDT:
logman create trace -n DacFxDebug -p "Microsoft-SQLServerDataTools" 0x800 -o "%LOCALAPPDATA%\DacFxDebug.etl" -ets
logman create trace -n SSDTDebug -p "Microsoft-SQLServerDataToolsVS" 0x800 -o "%LOCALAPPDATA%\SSDTDebug.etl" -ets
2) Go execute the command that's causing you grief
3) Execute the following commands to stop the logging trace:
logman stop DacFxDebug -ets
logman stop SSDTDebug -ets
4) Open 'eventvwr' in the Run dialog available from the Start Menu
5) Go to the right side 'Actions' pane, and click on 'Open Saved Log'.
6) When prompted to convert the log, click 'No'.
The logs will display under the 'Saved Logs' folder in the left hand navigation tree, and you'll be able to inspect the errors that occurred. Good luck with deployment!
Thursday, August 06, 2015
Adding extra files to your MSDeploy web package with MSBuild
I've recently started getting much more in depth with Azure. I've ported some web apps up into Azure, and now I need WebJobs. I've written the jobs, manually uploaded them into my web apps, tested them out and they work great. Now I need to ensure that the WebJobs get automatically deployed with my Web Application.
As it turns out, web jobs are just a sub folder with some naming conventions underneath the App_Data folder in your web application. Unfortunately, getting those files into that folder as part of the packaging process is a couple extra (non-obvious) steps.
Following this article on ASP.NET, I was able to add in the extra files. It took a lot more Googling than I care to admit to in order to find this article. As it turns out, you really need to pick your search terms well.
As it turns out, web jobs are just a sub folder with some naming conventions underneath the App_Data folder in your web application. Unfortunately, getting those files into that folder as part of the packaging process is a couple extra (non-obvious) steps.
Following this article on ASP.NET, I was able to add in the extra files. It took a lot more Googling than I care to admit to in order to find this article. As it turns out, you really need to pick your search terms well.
Monday, August 03, 2015
My website doesn't accept my Active Directory credentials and just keeps prompting me over and over. Or if it's Chrome, just gives me a middle finger straight up.
Recently, I've been having the problem of trying to reach some of the internal applications that my company develops that uses Windows Authentication. Thanks to this article:
http://www.leftycoder.com/windows-authentication-chrome-iis/
... I found out why. I had to remove the option for 'Negotiate' with Windows Authentication. The settings had changed when we moved our applications to a new IIS Web Site. Something to keep in mind.
http://www.leftycoder.com/windows-authentication-chrome-iis/
... I found out why. I had to remove the option for 'Negotiate' with Windows Authentication. The settings had changed when we moved our applications to a new IIS Web Site. Something to keep in mind.
Labels:
active,
active directory,
API,
app,
asp.net,
authentication,
directory,
iis,
mvc,
web,
windows
Thursday, July 30, 2015
Bitten by IIS, or lack thereof
Here at the office, we build a number of web applications. I recently started refactoring one such application to change and improve how we deploy it. As soon as I made the change to the .csproj to remove some old configurations and add new ones, I mysteriously started getting this error on our build machine (and only our build machine):
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\Web\Microsoft.Web.Publishing.targets (2664): Filename: redirection.configError: Cannot read configuration file
After examining the changes I made, I figured "there's nothing that should be causing this. WTF?" Then after a while, I went on to our build machine and found that we didn't actually have IIS installed on the build machines (which is a good idea from a security standpoint, because there's really no reason for a build machine to have IIS installed). So why did this start suddenly ?
I went and examined the exact line that was causing the problem in the targets file, and the only thing that appeared to be including this conditional statement was the flag 'IncludeIisSettings'. Sure enough, the old configuration which we never used before and were using now had this set.
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\Web\Microsoft.Web.Publishing.targets (2664): Filename: redirection.configError: Cannot read configuration file
After examining the changes I made, I figured "there's nothing that should be causing this. WTF?" Then after a while, I went on to our build machine and found that we didn't actually have IIS installed on the build machines (which is a good idea from a security standpoint, because there's really no reason for a build machine to have IIS installed). So why did this start suddenly ?
I went and examined the exact line that was causing the problem in the targets file, and the only thing that appeared to be including this conditional statement was the flag 'IncludeIisSettings'. Sure enough, the old configuration which we never used before and were using now had this set.
Thursday, July 09, 2015
A problem with redirect loops in IIS (8.5) with ASP.NET MVC 5 (and Identity)
Ever see something like this ?
http://localhost:80/MyApp/Account/Login?ReturnUrl=%2FMyApp%2FAccount%2FLogin%3FReturnUrl%3D%252FMyApp%252FAccount%252FLogin%253FReturnUrl%253D%25252FMyApp%25252FAccount%25252FLogin%25253FReturnUrl%25253D%2525252FMyApp%2525252FAccount%2525252FLogin%2525253FReturnUrl%2525253D%252525252FMyApp%252525252FAccount%252525252FLogin%252525253FReturnUrl%252525253D%25252525252FMyApp%25252525252FAccount%25252525252FLogin%25252525253FReturnUrl%25252525253D%2525252525252FMyApp%2525252525252FAccount%2525252525252FLogin%2525252525253FReturnUrl%2525252525253D%252525252525252FMyApp%252525252525252FAccount%252525252525252FLogin%252525252525253FReturnUrl%252525252525253D%25252525252525252FMyApp%25252525252525252FAccount%25252525252525252FLogin%25252525252525253FReturnUrl%25252525252525253D%2525252525252525252FMyApp%2525252525252525252FAccount%2525252525252525252FLogin%2525252525252525253FReturnUrl%2525252525252525253D%252525252525252525252FMyApp%252525252525252525252FAccount%252525252525252525252FLogin%252525252525252525253FReturnUrl%252525252525252525253D%25252525252525252525252FMyApp%25252525252525252525252FAccount%25252525252525252525252FLogin%25252525252525252525253FReturnUrl%25252525252525252525253D%2525252525252525252525252FMyApp%2525252525252525252525252FAccount%2525252525252525252525252FLogin%2525252525252525252525253FReturnUrl%2525252525252525252525253D%252525252525252525252525252FMyApp%252525252525252525252525252FAccount%252525252525252525252525252FLogin%252525252525252525252525253FReturnUrl%252525252525252525252525253D%25252525252525252525252525252FMyApp%25252525252525252525252525252FAccount%25252525252525252525252525252FLogin%25252525252525252525252525253FReturnUrl%25252525252525252525252525253D%2525252525252525252525252525252FMyApp%2525252525252525252525252525252FAccount%2525252525252525252525252525252FLogin%2525252525252525252525252525253FReturnUrl%2525252525252525252525252525253D%252525252525252525252525252525252FMyApp%252525252525252525252525252525252F
As it turns out, IIS can generate redirect loops whenever there's a freshly deployed (installed) MVC application that hasn't had its application pool correctly setup.
Just thought I'd put this here in case anybody else runs across it.
http://localhost:80/MyApp/Account/Login?ReturnUrl=%2FMyApp%2FAccount%2FLogin%3FReturnUrl%3D%252FMyApp%252FAccount%252FLogin%253FReturnUrl%253D%25252FMyApp%25252FAccount%25252FLogin%25253FReturnUrl%25253D%2525252FMyApp%2525252FAccount%2525252FLogin%2525253FReturnUrl%2525253D%252525252FMyApp%252525252FAccount%252525252FLogin%252525253FReturnUrl%252525253D%25252525252FMyApp%25252525252FAccount%25252525252FLogin%25252525253FReturnUrl%25252525253D%2525252525252FMyApp%2525252525252FAccount%2525252525252FLogin%2525252525253FReturnUrl%2525252525253D%252525252525252FMyApp%252525252525252FAccount%252525252525252FLogin%252525252525253FReturnUrl%252525252525253D%25252525252525252FMyApp%25252525252525252FAccount%25252525252525252FLogin%25252525252525253FReturnUrl%25252525252525253D%2525252525252525252FMyApp%2525252525252525252FAccount%2525252525252525252FLogin%2525252525252525253FReturnUrl%2525252525252525253D%252525252525252525252FMyApp%252525252525252525252FAccount%252525252525252525252FLogin%252525252525252525253FReturnUrl%252525252525252525253D%25252525252525252525252FMyApp%25252525252525252525252FAccount%25252525252525252525252FLogin%25252525252525252525253FReturnUrl%25252525252525252525253D%2525252525252525252525252FMyApp%2525252525252525252525252FAccount%2525252525252525252525252FLogin%2525252525252525252525253FReturnUrl%2525252525252525252525253D%252525252525252525252525252FMyApp%252525252525252525252525252FAccount%252525252525252525252525252FLogin%252525252525252525252525253FReturnUrl%252525252525252525252525253D%25252525252525252525252525252FMyApp%25252525252525252525252525252FAccount%25252525252525252525252525252FLogin%25252525252525252525252525253FReturnUrl%25252525252525252525252525253D%2525252525252525252525252525252FMyApp%2525252525252525252525252525252FAccount%2525252525252525252525252525252FLogin%2525252525252525252525252525253FReturnUrl%2525252525252525252525252525253D%252525252525252525252525252525252FMyApp%252525252525252525252525252525252F
As it turns out, IIS can generate redirect loops whenever there's a freshly deployed (installed) MVC application that hasn't had its application pool correctly setup.
Just thought I'd put this here in case anybody else runs across it.
Thursday, June 04, 2015
Getting started with Azure in PowerShell
As it turns out, Azure has a ton of cmdlets available in the PowerShell command line to help you quickly and easily manage aspects of Azure.
- Install the Azure PowerShell from the Microsoft Web Platform Installer
- Install the Azure AD Module from the links on this page.
- After installing the Microsoft Online pack, you may have to copy the 'MSOnline' and 'MSOnlineExtended' folders from 'C:\windows\system32\WindowsPowerShell\v1.0\Modules' to 'C:\Windows\SysWOW64\WindowsPowerShell\v1.0\Modules' if you're running a server version of Windows
- Open a PowerShell session as Administrator
- Run the command "Import-Module azure"
- Run the command "Import-Module MSOnline"
- Add-AzureAccount -- Allows you to enter credentials and register your account with PowerShell so that you can manage it
- Get-AzureAccount -- shows you the currently active accounts
- Get-AzureSubscription -- shows the subscriptions available for the currently selected azure account
Also, to manage the roles in your Azure Active Directory, check out this page on Microsoft's Azure section.
To start log streaming for a specific web application, use this command:
PS C:\> Get-AzureWebsiteLog -Tail -Name mywebsitenamehere
Beginning in version 0.8.0, the Azure PowerShell installation includes more than one PowerShell module. You must explicitly decide whether to use the commands that are available in the Azure module or the Azure Resource Manager module. To make it easy to switch between them, we have added a new cmdlet, Switch-AzureMode, to the Azure Profile module.
When you use Azure PowerShell, the cmdlets in the Azure module are imported by default. To switch to the Azure Resource Manager module, use the Switch-AzureMode cmdlet. It removes the Azure module from your session and imports the Azure Resource Manager and Azure Profile modules.
To switch to the AzureResoureManager module, type:
PS C:\> Switch-AzureMode -Name AzureResourceManager
To switch back to the Azure module, type:
PS C:\> Switch-AzureMode -Name AzureServiceManagement
By default, Switch-AzureMode affects only the current session. To make the switch effective in all PowerShell sessions, use the Global parameter of Switch-AzureMode.
To start log streaming for a specific web application, use this command:
PS C:\> Get-AzureWebsiteLog -Tail -Name mywebsitenamehere
Sunday, May 31, 2015
Getting access to roles and group claims in Azure AD using the Graph API
Check this link out. It contains a tutorial on how to get Roles and Groups in Azure AD, so that you can have a single code-base for checking roles and groups regardless of whether you're using Azure AD or on-prem AD.
Also check out this link to an Azure AD example on GitHub for getting Group access in your applications
Also check out this link to an Azure AD example on GitHub for getting Group access in your applications
Tuesday, May 26, 2015
Implementing delegated authentication from an Azure MVC web app to an Azure Web API web service
Follow the information on this tutorial. Contained within that link, is this tutorial on authenticating a web app with delegated user identity to a web API service.
Authenticating users on an Azure web site (MVC) using Azure Active Directory (AAD)
Follow this guide provided on Github. It provides all of the information you need to enable the simplest form of Azure AD authentication in an MVC app. It can be used as the beginning step to getting a fully authenticated MVC web app / web API stack.
Monday, May 18, 2015
Creating an Intranet MVC 5 application using Windows Authentication that connects to a separate Intranet Web API 2 application also using Windows Authentication
Recently I wanted to create an Intranet MVC application using Windows Authentication that connects to a separate, pre-existing Intranet Web API 2 web service that also uses Windows Authentication. In order to get the Windows Authentication of the MVC application propagated to authenticate with the Web API 2 web service, I had to do the following:
1) Place the following in both applications' <system.web> sections in their respective configuration files.
4) Use the following to connect to Web API 2:
As a side note, apparently there's also a way to change the settings so that you don't have to modify the global aspnet.config file, you can do it on a per-AppPool basis. The technique is described here, though I've never tried it myself.
1) Place the following in both applications' <system.web> sections in their respective configuration files.
2) Update the .NET aspnet.config file located at "C:\Windows\Microsoft.NET\Framework\v4.0.30319\Aspnet.config" to change the following settings to the following values:<authentication mode="Windows" /><authorization><deny users="?" /></authorization>
3) In the code for the MVC app that wants to call the Web API 2 app, do the following:<legacyImpersonationPolicy enabled="false"/><alwaysFlowImpersonationPolicy enabled="true"/>
This last bit is necessary to ensure that the currently authenticated user in the MVC app gets correctly propagated to the Web API 2 app. In the service that's mentioned in the code above, you'll also need to do the following for interacting with Web API 2:WindowsIdentity identity = (WindowsIdentity) this.HttpContext.User.Identity;using (identity.Impersonate()){searchModel.SearchResults = this.webApiService.FindWebApiItems(searchModel.SearchCriteria);}
4) Use the following to connect to Web API 2:
HttpClientHandler handler = new HttpClientHandler
{
PreAuthenticate = true,
UseDefaultCredentials = true,
Credentials = CredentialCache.DefaultNetworkCredentials
};
using (HttpClient client = new HttpClient(handler))
{
string result = client.GetStringAsync(uriBuilder.Uri).GetAwaiter().GetResult();
IList<MyWebApiModel> webApiModels = JsonConvert.DeserializeObject<MyWebApiModel[]>(result);
return webApiModels;
}
You should now have working code to propagate Windows Authentication via services.
As a side note, apparently there's also a way to change the settings so that you don't have to modify the global aspnet.config file, you can do it on a per-AppPool basis. The technique is described here, though I've never tried it myself.
Labels:
API,
asp.net,
authentication,
impersonation,
mvc,
web,
webapi,
webapi2,
windows
Monday, April 27, 2015
A little gotcha with the Microsoft Task Parallel Library (TPL) Dataflow library
I've recently started using the Microsoft TPL Dataflow library in order to help improve the performance of some of our product's scheduled jobs. However, today, I ran into a little gotcha that's pretty important. When you're linking one block to another block, you must always ensure that the source block links to at least one target block that accepts its messages, otherwise it'll most likely deadlock!
Subscribe to:
Posts (Atom)