Skip to content

Sample using Transactions(via MSDTC) on Rest Calls to .Net Framework Service(Via System.Transactions)

Notifications You must be signed in to change notification settings

pcbl/MicroService.2PC.Transaction

Repository files navigation

Even that Transactions are not recommended on MicroServices(that usually is a sign that your services were mistakenly splitted), there are some situations(usually legacy calls) that demans some transaction control...

alternative text

REMARK: The .Net Code/.Net 5 service is not working, still... :-| More Infos: //dotnet/runtime#715

MicroService.2PC.Transaction

Sample using Transactions(via MSDTC) on Rest Calls to .Net Framework Service(Via System.Transactions)

Created based on this article: https://www.c-sharpcorner.com/article/distributed-transactions-with-webapi-across-application-domains/

Getting it to work

  1. Create a Database with a table named LogTable with this structure:
CREATE TABLE [dbo].[LogTable](
                [ID] [int] IDENTITY(1,1) NOT NULL,
                [Name] [varchar](50) NOT NULL,
CONSTRAINT [PK_LogTable] PRIMARY KEY CLUSTERED 
(
                [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
  1. If needed, just update the DB connectionstring on the NetFrwService\Web.Config

  2. Start the solution with both Projects(Multiple) set as Startup Project. Press enter on the console application. It will run a loop of 2 calls to the service withina transactionscope. Between the calls it is waiting 10 seconds... Between calls you can see the table is locked and that only everythign is fine, the Transaction will be commited.

#The important Bits What really matters is:

  • When the HTTP Client makes the request, we inject a header named "TransactionToken" with Transaction Propagation Token Serialized as Base64:

    var token = TransactionInterop.GetTransmitterPropagationToken(Transaction.Current);
    request.Headers.Add("TransactionToken", Convert.ToBase64String(token));

  • When the Rest Service receives the request, it checks for the "TransactionToken" header and creates a transaction Scope connected with the transaction started on the Caller. We do this over a Filter:

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
    if (actionContext.Request.Headers.Contains(TransactionId))
    {
    var values = actionContext.Request.Headers.GetValues(TransactionId);
    if (values != null && values.Any())
    {
    byte[] transactionToken = Convert.FromBase64String(values.FirstOrDefault());
    var transaction = TransactionInterop.GetTransactionFromTransmitterPropagationToken(transactionToken);
    var transactionScope = new TransactionScope(transaction);
    actionContext.Request.Properties.Add(TransactionId, transactionScope);
    }
    }
    }
    /// <summary>
    /// Rollback or commit transaction.
    /// </summary>
    /// <param name="actionExecutedContext">The action executed context.</param>
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
    if (actionExecutedContext.Request.Properties.Keys.Contains(TransactionId))
    {
    var transactionScope = actionExecutedContext.Request.Properties[TransactionId] as TransactionScope;
    if (transactionScope != null)
    {
    if (actionExecutedContext.Exception != null)
    {
    Transaction.Current.Rollback();
    }
    else
    {
    transactionScope.Complete();
    }
    transactionScope.Dispose();
    actionExecutedContext.Request.Properties[TransactionId] = null;
    }
    }

Note that the Controller Action that needs to be "transactionable" have an attribute(EnlistToDistributedTransactionActionFilter) to use the filter:

[EnlistToDistributedTransactionActionFilter]

Obviously, both machines needs to have access to the MSDTC which is coordinating the transaction. Otherwise it will not work.

ENJOY

About

Sample using Transactions(via MSDTC) on Rest Calls to .Net Framework Service(Via System.Transactions)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published