Rajnish Noonia

Tag: .NET

  • .NET 8 Cryptography: AES-GCM, PBKDF2, and Secure Key Management

    Data encryption in financial systems is a regulatory and architectural baseline. With .NET 8 LTS (November 2023), the System.Security.Cryptography namespace has changed significantly: several APIs widely used in earlier .NET versions are now obsolete or removed, and the recommended patterns for symmetric encryption, key derivation, and asymmetric key transport have all been updated. This post covers the current .NET 8 approach to AES encryption (both CBC and GCM modes), PBKDF2 key derivation, RSA key exchange, and practical hybrid encryption — with guidance on what changed and why it matters for enterprise financial applications.

    What Changed from Earlier .NET Versions

    If you worked with .NET cryptography before .NET 6, several classes you may have relied on are now obsolete or removed in .NET 8:

    • RijndaelManaged — removed in .NET 8. Use Aes.Create() instead. RijndaelManaged throws PlatformNotSupportedException on .NET 8.
    • MD5CryptoServiceProvider, SHA1CryptoServiceProvider — deprecated. Use the static MD5.HashData() and SHA256.HashData() methods introduced in .NET 7.
    • PasswordDeriveBytes — obsolete. Use Rfc2898DeriveBytes (PBKDF2) with SHA-256 or SHA-512, or the new static Rfc2898DeriveBytes.Pbkdf2() method in .NET 6+.
    • RSACryptoServiceProvider — works but is a legacy Windows CAPI wrapper. Prefer RSA.Create() for cross-platform behaviour and modern padding support.

    Symmetric Encryption — AES in .NET 8

    AES is the standard for symmetric encryption. .NET 8 supports two modes that matter architecturally: AES-CBC (cipher-block chaining — confidentiality only) and AES-GCM (Galois/Counter Mode — authenticated encryption providing both confidentiality and integrity). For any new system, prefer AES-GCM: it detects ciphertext tampering before decryption, which AES-CBC cannot. AES-CBC without a separate MAC is vulnerable to padding oracle attacks.

    AES-GCM — Authenticated Encryption (Recommended)

    using System.Security.Cryptography;
    
    public static class AesGcmEncryption
    {
        public static (byte[] ciphertext, byte[] nonce, byte[] tag) Encrypt(
            byte[] plaintext, byte[] key)
        {
            var nonce = RandomNumberGenerator.GetBytes(AesGcm.NonceByteSizes.MaxSize);
            var ciphertext = new byte[plaintext.Length];
            var tag = new byte[AesGcm.TagByteSizes.MaxSize];
    
            using var aes = new AesGcm(key, AesGcm.TagByteSizes.MaxSize);
            aes.Encrypt(nonce, plaintext, ciphertext, tag);
    
            return (ciphertext, nonce, tag);
        }
    
        public static byte[] Decrypt(byte[] ciphertext, byte[] key, byte[] nonce, byte[] tag)
        {
            var plaintext = new byte[ciphertext.Length];
    
            using var aes = new AesGcm(key, AesGcm.TagByteSizes.MaxSize);
            aes.Decrypt(nonce, ciphertext, tag, plaintext);
    
            return plaintext;
        }
    }

    AES-CBC (where backward compatibility requires it)

    using System.Security.Cryptography;
    
    public static class AesCbcEncryption
    {
        public static (byte[] ciphertext, byte[] iv) Encrypt(byte[] plaintext, byte[] key)
        {
            using var aes = Aes.Create();
            aes.Key = key;
            aes.GenerateIV();
    
            using var ms = new MemoryStream();
            using var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write);
            cs.Write(plaintext);
            cs.FlushFinalBlock();
    
            return (ms.ToArray(), aes.IV);
        }
    
        public static byte[] Decrypt(byte[] ciphertext, byte[] key, byte[] iv)
        {
            using var aes = Aes.Create();
            aes.Key = key;
            aes.IV = iv;
    
            using var ms = new MemoryStream(ciphertext);
            using var cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Read);
            using var output = new MemoryStream();
            cs.CopyTo(output);
            return output.ToArray();
        }
    }

    Key Derivation — PBKDF2 with SHA-256

    Never use a raw password as an encryption key. Password-based keys must be derived using a key derivation function that applies a computationally expensive hash to slow down brute-force attacks. PBKDF2 (Password-Based Key Derivation Function 2) is the NIST-recommended approach. In .NET 8, use the static Rfc2898DeriveBytes.Pbkdf2() method with SHA-256 and a minimum of 600,000 iterations — the 2023 OWASP recommendation for PBKDF2-HMAC-SHA256.

    using System.Security.Cryptography;
    
    public static class KeyDerivation
    {
        public static byte[] DeriveKey(string password, byte[] salt, int keyLengthBytes = 32)
        {
            return Rfc2898DeriveBytes.Pbkdf2(
                password: password,
                salt: salt,
                iterations: 600_000,
                hashAlgorithm: HashAlgorithmName.SHA256,
                outputLength: keyLengthBytes);
        }
    
        public static byte[] GenerateSalt(int length = 16)
            => RandomNumberGenerator.GetBytes(length);
    }

    For machine-to-machine encryption in production financial services, avoid password-derived keys entirely. Generate cryptographically random AES keys and store them in a managed key store — Azure Key Vault, AWS Secrets Manager, or an HSM. Key rotation, access control, and audit logs come for free from the platform rather than being built from scratch.

    Asymmetric Encryption — RSA in .NET 8

    RSA is used for key transport and digital signatures, not for bulk data encryption — it is orders of magnitude slower than AES and limited by key size in the amount of data it can encrypt directly. The standard architectural pattern is hybrid encryption: encrypt the data payload with AES-GCM using a freshly generated key, then encrypt that AES key with the recipient’s RSA public key.

    using System.Security.Cryptography;
    
    public static class RsaEncryption
    {
        public static RSA CreateKeyPair() => RSA.Create(4096);
    
        public static byte[] Encrypt(byte[] data, RSA publicKey)
            => publicKey.Encrypt(data, RSAEncryptionPadding.OaepSHA256);
    
        public static byte[] Decrypt(byte[] ciphertext, RSA privateKey)
            => privateKey.Decrypt(ciphertext, RSAEncryptionPadding.OaepSHA256);
    
        public static byte[] Sign(byte[] data, RSA privateKey)
            => privateKey.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
    
        public static bool Verify(byte[] data, byte[] signature, RSA publicKey)
            => publicKey.VerifyData(data, signature,
                   HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
    }

    Hybrid Encryption Pattern

    The practical pattern for encrypting arbitrarily large payloads in financial systems combines both approaches — RSA for secure key transport, AES-GCM for the actual data — and uses CryptographicOperations.ZeroMemory to scrub key material from managed memory after use.

    using System.Security.Cryptography;
    
    public static class HybridEncryption
    {
        public static (byte[] encryptedKey, byte[] nonce, byte[] tag, byte[] ciphertext)
            Encrypt(byte[] plaintext, RSA recipientPublicKey)
        {
            var aesKey = RandomNumberGenerator.GetBytes(32);
            try
            {
                var (ciphertext, nonce, tag) = AesGcmEncryption.Encrypt(plaintext, aesKey);
                var encryptedKey = RsaEncryption.Encrypt(aesKey, recipientPublicKey);
                return (encryptedKey, nonce, tag, ciphertext);
            }
            finally
            {
                CryptographicOperations.ZeroMemory(aesKey);
            }
        }
    
        public static byte[] Decrypt(
            byte[] encryptedKey, byte[] nonce, byte[] tag,
            byte[] ciphertext, RSA recipientPrivateKey)
        {
            var aesKey = RsaEncryption.Decrypt(encryptedKey, recipientPrivateKey);
            try
            {
                return AesGcmEncryption.Decrypt(ciphertext, aesKey, nonce, tag);
            }
            finally
            {
                CryptographicOperations.ZeroMemory(aesKey);
            }
        }
    }

    Architectural Guidance

    • Prefer AES-GCM over AES-CBC for new systems. Authenticated encryption prevents bit-flipping and padding oracle attacks that AES-CBC alone cannot stop.
    • Never reuse a nonce with the same AES-GCM key. Nonce reuse in GCM completely breaks confidentiality — both the keystream and the plaintext become recoverable. Generate a fresh random nonce per message.
    • Use RSA-OAEP-SHA256 padding. PKCS#1 v1.5 padding is vulnerable to the Bleichenbacher adaptive chosen-ciphertext attack. OAEP is the current standard.
    • Use PBKDF2 with SHA-256 and ≥ 600,000 iterations for any password-derived key. For non-interactive M2M keys, use RandomNumberGenerator.GetBytes(32) and store in a managed secrets store.
    • Zero key material after use with CryptographicOperations.ZeroMemory. In long-running services, uncleared key bytes can persist in managed heap memory until the next GC cycle — and potentially be readable via memory dumps.
    • Store private keys outside the application. In production financial systems, RSA private keys belong in HSMs or platform key vaults (Azure Key Vault, AWS KMS). Never commit key material to configuration files or source control.
    • Use certificate-backed RSA where available. X.509 certificates provide key identity, expiry, and chain-of-trust that raw key bytes do not — essential for regulated environments such as capital markets platforms.
  • .NET 8 CLR Internals: RyuJIT, Dynamic PGO, and the Garbage Collector

    With .NET 8 LTS shipping in November 2023, it is worth revisiting what the Common Language Runtime actually does under the hood — not just conceptually, but with the specific advances that directly affect how you design high-throughput, low-latency applications. This post covers the CoreCLR execution model, the RyuJIT compilation pipeline, tiered compilation and Dynamic PGO, the .NET 8 garbage collector, and Native AOT, with a practical lens on financial platform and trading system engineering.

    CoreCLR — The .NET 8 Execution Engine

    The CLR — known as CoreCLR since .NET Core — is the managed execution engine for .NET. It provides the runtime environment in which compiled .NET code runs, regardless of operating system or CPU architecture. The major subsystems are the same as the original design, but the implementation has been rebuilt and significantly advanced across eight major releases.

    • Class Loader: Loads assemblies and types on demand. In .NET 8, AssemblyLoadContext replaces AppDomain as the isolation primitive — enabling unloadable plugin assemblies, hot-reloadable modules, and isolated component boundaries essential for extensible platform architectures.
    • RyuJIT: The cross-platform JIT compiler that translates CIL (Common Intermediate Language) to native machine code. In .NET 8, RyuJIT includes AVX-512 hardware intrinsic support, improved loop vectorisation, and better register allocation — producing faster native code, particularly for numeric and financial computation.
    • Tiered Compilation: Methods start as quickly compiled Tier-0 code. Hot methods are recompiled at Tier-1 with full optimisations. This minimises startup latency while achieving peak throughput on critical paths.
    • Dynamic PGO (Profile-Guided Optimisation): Introduced in .NET 6 and significantly improved in .NET 8. The runtime collects profiling data at Tier-1 and uses it to drive a third compilation pass — applying type specialisation and call-site inlining that cannot be determined ahead-of-time.
    • Garbage Collector: Generational, concurrent, server-aware. The .NET 8 GC includes DATAS (Dynamic Adaptation to Application Size) — covered below.
    • Exception Manager: Zero-cost exception model for the happy path. Structured exception handling overhead is only paid when an exception is actually thrown.
    • Thread Support: The .NET 8 ThreadPool uses work-stealing queues and adaptive IO thread management. Task, ValueTask, and async/await are all built on top of the thread pool scheduler.

    RyuJIT and Dynamic PGO

    Dynamic PGO is the most architecturally significant compilation advance in recent .NET versions. At runtime, the JIT records which concrete types flow through virtual call and interface dispatch slots. On the third compilation pass (Tier-2), it replaces those dispatch sites with direct calls guarded by a type check — turning a virtual dispatch into a predictable branch. For trading platforms with polymorphic data pipelines (order handlers, risk calculators, streaming market data processors), this can eliminate 10–30% of dispatch overhead with no source code changes.

    Dynamic PGO is enabled by default in .NET 8. You can verify its effect on specific hot paths using BenchmarkDotNet with the MemoryDiagnoser attribute and the DOTNET_TieredPGO=1 environment variable. For latency-sensitive services, profile under representative load before drawing conclusions — cold JIT behaviour can mask the steady-state gains.

    The .NET 8 Garbage Collector

    The GC is the most architecturally consequential runtime subsystem for high-throughput services. Understanding it shapes decisions about allocation rates, object lifetimes, pooling strategies, and latency SLAs long before you write a line of application code.

    Generations and the Large Object Heap

    The .NET GC is generational. Objects are allocated into Generation 0. Survivors are promoted to Gen 1, then Gen 2. Gen 2 collects infrequently and can trigger a full blocking pause — the primary latency risk in real-time financial services.

    Objects larger than 85,000 bytes land on the Large Object Heap (LOH). The LOH is collected alongside Gen 2 and is not compacted by default, accumulating fragmentation over long-running service lifetimes. The architectural mitigation is to avoid LOH allocations entirely on hot paths using ArrayPool<T>, MemoryPool<T>, and Span<T>-based APIs.

    DATAS — Dynamic Adaptation to Application Size

    New in .NET 8, DATAS allows the Server GC to dynamically resize heap sections based on live data rather than provisioning a fixed heap per CPU core at startup. For containerised deployments — where your service runs in a Kubernetes pod with a strict memory limit — this matters significantly: the GC no longer over-provisions heap relative to the container ceiling, reducing OOM risk and improving memory efficiency under variable load without manual GC configuration.

    Zero-allocation patterns in .NET 8

    The primary tool for reducing GC pressure on hot paths is avoiding allocations entirely. .NET 8 provides a mature set of primitives for this:

    • Span<T> and Memory<T>: Stack-allocated or pooled slices of contiguous memory. Zero heap allocation for parsing, serialisation, and buffer manipulation. Central to high-frequency data pipelines.
    • ArrayPool<T>.Shared: Rent and return byte buffers from a thread-local pool. Eliminates LOH allocations for large temporary arrays such as serialised market data frames or network payloads.
    • stackalloc with Span<T>: Allocate fixed-size buffers on the stack — no GC involvement. Useful for small fixed-width financial records, message headers, and cryptographic keys.
    • IMemoryOwner<T> and MemoryPool<T>: Lifetime-managed pooled memory for async pipelines — returned to the pool when the owning scope disposes.
    // Zero-allocation price parsing using Span<T> — no heap allocation on the hot path
    public static decimal ParsePrice(ReadOnlySpan<char> input)
    {
        return decimal.Parse(input, System.Globalization.NumberStyles.Any);
    }
    
    // Rent a buffer from the pool instead of allocating a new array
    public static void ProcessMarketDataFrame(int frameSize)
    {
        byte[] buffer = ArrayPool<byte>.Shared.Rent(frameSize);
        try
        {
            var span = buffer.AsSpan(0, frameSize);
            // ... process frame data without additional allocations
        }
        finally
        {
            ArrayPool<byte>.Shared.Return(buffer);
        }
    }

    Native AOT in .NET 8

    Native AOT (Ahead-Of-Time compilation) is a first-class publish target in .NET 8. It compiles the application entirely to native machine code at build time — eliminating the JIT, the CLR startup overhead, and a significant proportion of runtime metadata. The result is a self-contained binary with sub-millisecond startup times and a substantially smaller memory footprint.

    Architectural trade-offs to evaluate before adopting Native AOT: it is well suited for serverless functions (Azure Functions, AWS Lambda) where cold-start latency is in the SLA, sidecar processes, and CLI tooling where a self-contained executable replaces a runtime dependency. It is not suitable for reflection-heavy frameworks, dynamic plugin loading via AssemblyLoadContext, or libraries relying on runtime type resolution — all of which require IL metadata that AOT strips.

    How the Execution Pipeline Works

    When you build a .NET 8 project, Roslyn compiles your C# source into CIL (Common Intermediate Language) — a CPU-independent instruction set stored in a portable executable alongside rich metadata (type definitions, method signatures, custom attributes). At runtime:

    1. The CoreCLR host (dotnet or the application executable) loads and initialises the runtime, applying any environment-based GC and threading configuration.
    2. The Class Loader reads the PE metadata and resolves assembly dependencies via AssemblyLoadContext, creating isolation boundaries for plugins and hot-reloadable components.
    3. On the first call to a method, RyuJIT compiles the CIL to Tier-0 native code and caches it in the JIT code heap.
    4. The call counter increments. Once the threshold is reached, the method is recompiled to optimised Tier-1 code. With Dynamic PGO active, profiling data drives a further Tier-2 pass applying type specialisation for the hottest dispatch sites.
    5. The Server GC manages object lifetime automatically across per-CPU heaps, collecting in parallel to maximise throughput while background threads minimise Gen 2 pause duration.

    Architectural Takeaways

    Understanding the .NET 8 runtime model informs architectural decisions that cannot be made correctly from framework documentation alone:

    • GC pause budgets must be part of SLA design for real-time services — not an afterthought. Instrument allocation rates in production using EventPipe and dotnet-counters before optimising.
    • Allocation-free hot paths using Span<T>, pooling, and stackalloc are the primary levers for achieving sub-millisecond P99 latency in financial data services. Framework-level throughput gains (Dynamic PGO, SIMD) are secondary to eliminating unnecessary allocations.
    • DATAS makes .NET 8 services significantly better-behaved in Kubernetes with memory limits — the GC now respects cgroup boundaries rather than provisioning heap against total host memory.
    • Native AOT changes the deployment model: smaller, faster-starting processes at the cost of dynamic loading capability — a meaningful trade-off in containerised, serverless, and edge topologies.
    • AssemblyLoadContext is the correct isolation primitive for plugin architectures in .NET 8. AppDomain is not available in CoreCLR.
  • Reactive Extensions (Rx) Data Streaming

    You have probably heard about Reactive Extensions, a library from Microsoft that greatly simplifies working with asynchronous data streams and allows to query them with LINQ operators.In my previous post I briefly discussed about loading data via entity framework asynchronously however it lacks getting chunks of data. This post demonstrates how to use Reactive Extensions for loading data from database asynchronously in chunks covering brief around Reactive extension library.

    Reactive extensions (Rx)
    The Reactive Extensions (Rx) is a library for composing asynchronous and event-based programs using observable sequences and LINQ-style query operators. Using Rx, developers represent asynchronous data streams with Observables, query asynchronous data streams using LINQ operators, and parameterize the concurrency in the asynchronous data streams using Schedulers. Simply put, Rx = Observables + LINQ + Schedulers.Data sequences can take many forms, such as a stream of data from a file or web service, web services requests, system notifications, or a series of events such as user input. Reactive Extensions represents all these data sequences as observable sequences. An application can subscribe to these observable sequences to receive asynchronous notifications as new data arrive. The Rx library is available for desktop application development in .NET. It is also released for Silverlight, Windows Phone 7 and JavaScript.

    Reactive programming allows you to turn those aspects of your code that are currently imperative into something much more event-driven and flexible.Reactive programming can be applied to a range of situations—from WPF applications to Windows Phone apps—to improve coding efficiency and boost performance.

    Code snippets to asynchronous load data via entity framework in batches of 200 records.

    public void LoadPostCodes()
    {
     btnStatus.Content = "Started";
     listBox1.Items.Clear();
     (from p in cx.MAS_PostCode select p)
     .ToObservable(Scheduler.NewThread)
     .Buffer(200)
     .ObserveOn(SynchronizationContext.Current)
     .Subscribe(ld =>
     {
     foreach (var item in ld)
     {
     ListBoxItem litem = new ListBoxItem();
     litem.Content = string.Format("{0} {1}", item.PC_PostCode, item.PC_Address1);
     listBox1.Items.Add(litem);
     listBox1.ScrollIntoView(litem);
     }
     button1.Content = listBox1.Items.Count.ToString();
     },
     () => { btnStatus.Content = "Finished"; }
     );
    }

    Have finished writing MVVM(Nano View model) based scenario & Rx implementations …

    Will write soon and publish code..

    Regards
    Rajnish

  • The Future of the Web Stack: OWIN and ASP.NET vNext

    The ASP.NET Framework has been around for over ten years, and the platform has enabled the development of countless Web sites and services. As Web application development strategies have evolved, the framework has been able to evolve in step with technologies like ASP.NET MVC and ASP.NET Web API.

    Web Evolution

    • Classic ASP – At the time, ASP was one of the primary technologies for creating dynamic, data-driven Web sites and applications by interweaving markup and server-side script. The ASP runtime supplied server-side script with a set of objects that abstracted core aspects of the underlying HTTP protocol and Web server and provided access to additional services such session and application state management, cache, etc. While powerful, classic ASP applications became a challenge to manage as they grew in size and complexity. This was largely due to the lack of structure found in in scripting environments coupled with the duplication of code resulting from the interleaving of code and markup
    • ASP.Net – The first version of ASP.NET – also known as “Web Forms” provided a similar design time experience along with a server-side event model for user interface components and a set of infrastructure features (such as ViewState) to create a seamless developer experience between client and server side programming. Web Forms effectively hid the Web’s stateless nature under a stateful event model that was familiar to WinForms developers.
      • ASP.Net MVC – ASP.NET team took several evolutionary steps to enable ASP.NET as a family of pluggable Web components rather than a single framework.One of the early changes was the rise in popularity of the well-known model-view-controller (MVC) design pattern thanks to Web development frameworks like Ruby on Rails. This style of building Web applications gave the developer greater control over her application’s markup while still preserving the separation of markup and business logic, which was one of the initial selling points for ASP.NET.
      • ASP.Net Web API – Another major shift in Web application development was the shift from dynamic, server-generated Web pages to static initial markup with dynamic sections of the page generated from client-side script communicating with backend Web APIs through AJAX requests. This architectural shift helped propel the rise of Web APIs, and the development of the ASP.NET Web API framework. As in the case of ASP.NET MVC, the release of ASP.NET Web API provided another opportunity to evolve ASP.NET further as a more modular framework.

    By decoupling framework components from one another and then releasing them on NuGet, frameworks could now iterate more independently and more quickly.A modern Web application generally supports static file serving, dynamic page generation, Web API, and more recently real-time/push notifications. Expecting that each of these services should be run and managed independently was simply not realistic.

    What was needed was a single hosting abstraction that would enable a developer to compose an application from a variety of different components and frameworks, and then run that application on a supporting host.

    The Open Web Interface for .NET (OWIN)

    Inspired by the benefits achieved by Rack in the Ruby community, several members of the .NET community set out to create an abstraction between Web servers and framework components. Two design goals for the OWIN abstraction were that it was simple and that it took the fewest possible dependencies on other framework types. These two goals help ensure:

    New components could be more easily developed and consumed.
    Applications could be more easily ported between hosts and potentially entire platforms/operating systems.
    The resulting abstraction consists of two core elements. The first is the environment dictionary. This data structure is responsible for storing all of the state necessary for processing an HTTP request and response, as well as any relevant server state. The environment dictionary is defined as follows:

    IDictionary<string, object>
    An OWIN-compatible Web server is responsible for populating the environment dictionary with data such as the body streams and header collections for an HTTP request and response. It is then the responsibility of the application or framework components to populate or update the dictionary with additional values and write to the response body stream.

    In asp.net WebApi v2, the OWIN pipeline becomes the default. It is eventually going to be the standard pipeline under any asp.net project.

    Without OWIN, the asp.net bits are coupled to the way IIS communicates with the application. OWIN abstracts web servers and framework components. That means that your application code will now be aware of the OWIN interface, but not of the webserver that is serving the request.

    In return, applications can be more easily ported between hosts and potentially entire platforms/operating systems. For example, the ability to host an application in a console or any process allows Mono to host it without efforts…

    The second aspect is that it works as a pipeline.

    You can plug any middlewares (and as many as you want) between the webserver and your application.
    This allows for more modular solutions. You can develop redistributable middlewares that can impact the request/response coming to/from your application, but keep these modules separated from the application code.

    To persuade yourself of the benefits of this modular approach, take a look at the nuget packages available for OWIN : http://www.nuget.org/packages?q=owin

    A lot of these packages were previously core asp.net functionality, and have been extracted as middleware.
    For example, adding support to login using various OAuth providers becomes an infrastructure concern (a middleware) and does not need to be part of your application code anymore :

    Learn more about OWIN

    Project Katana

    Whereas both the OWIN specification and Owin.dll are community owned and community run open source efforts, the Katana project represents the set of OWIN components that, while still open source, are built and released by Microsoft. These components include both infrastructure components, such as hosts and servers, as well as functional components, such as authentication components and bindings to frameworks such as SignalR and ASP.NET Web API. The project has the following three high level goals:

    Portable – Components should be able to be easily substituted for new components as they become available. This includes all types of components, from the framework to the server and host. The implication of this goal is that third party frameworks can seamlessly run on Microsoft servers while Microsoft frameworks can potentially run on third party servers and hosts.
    Modular/flexible – Unlike many frameworks which include a myriad of features that are turned on by default, Katana project components should be small and focused, giving control over to the application developer in determining which components to use in her application.
    Lightweight/performant/scalable – By breaking the traditional notion of a framework into a set of small, focused components which are added explicitly by the application developer, a resulting Katana application can consume fewer computing resources, and as a result, handle more load, than with other types of servers and frameworks. As the requirements of the application demand more features from the underlying infrastructure, those can be added to the OWIN pipeline, but that should be an explicit decision on the part of the application developer. Additionally, the substitutability of lower level components means that as they become available, new high performance servers can seamlessly be introduced to improve the performance of OWIN applications without breaking those applications.

    And Now.. 

    ASP.Net 5 – vNext 

    The next generation of ASP.net

    ASP.NET 5 is a significant redesign of ASP.NET.

    ASP.NET 5 includes the following features:

    • New flexible and cross-platform runtime
    • ASP.NET MVC and Web API have been unified into a single programming model
    • New modular HTTP request pipeline
    • Cloud-ready environment configuration
    • Modular design, depedency injection and lot more.
    • Unified programming model that combines MVC, Web API,SignalR and Web Pages
    • Ability to see changes without re-building the project
    • Side-by-side versioning of the .NET Framework
    • Ability to self-host or host on IIS
    • New tools in Visual Studio 2015
    • Open source in GitHub
    • Can run on Mono, on Mac and Linux

    Learn more : http://www.asp.net/vnext

     

  • Enterprise configuration management

    Almost every application requires some form of configuration information. This information can be as simple as a database connection string or as complex as multipart and hierarchical user preference information. How and where to store an application’s configuration data are questions you often face as a developer.

    Any large enterprise application has many moving blocks. They all need to be configured for a proper working of the application. As the application size increases or for scalability the same configuration has to be repeated in different applications. For most applications once the configuration has been changed the application needs to be restarted.

    Sample Code (create a blank console project, add json.net nuget)

    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    using System.Collections.Generic;
    using System.Linq;
    
    namespace CM
    {
        // configuration management API, 
        //1. allow clients specify typesafe models for configuations
        //2. Store flat data on server (table) which is easy to edit
        //3. can be extended to have inheritance of values (overrides)
        //4. can be extended to lock / unlock certain property by admins etc.
        
        class Program
        {
            //Sample configuration model
            internal class SampleConfigModal
            {
                public SampleConfigModal()
                {
                    Address = new Address();
                }
                public string Name { get; set; }
                public Address Address { get; set; }
                public int Age { get; set; }
    
    
            }
            public class Address
            {
                public string Street { get; set; }
    
            }
    
            // this is how client api will look like
            static void Main(string[] args)
            {
                // sample client code
                var data = new SampleConfigModal() { Name = "Rajnish", Age = 18, Address = new Address() { Street = "Oxley" } };
    
                // save Configuration
                SaveConfiguration("app", "section", data);
    
                //get Configuration
                var data2 = GetConfiguration("app", "section");
            }
    
            // Client side framework api -> call to rest end point
            private static T GetConfiguration(string appName, string SectionName) where T : new()
            {
                var defaultValue = new T();
                var samplePayload = JsonConvert.SerializeObject(defaultValue);
                var payload = GetConfiguration(appName, SectionName, samplePayload);
                return JsonConvert.DeserializeObject(payload);
            }
    
            // Client side framework api -> call to rest end point
            private static void SaveConfiguration(string appName, string SectionName, T data)
            {
                var payload = Newtonsoft.Json.JsonConvert.SerializeObject(data);
                SaveConfigurationa(appName, SectionName, payload);
            }
    
    
            //---------------------------------------- Server Code -------------------------- 
            //-------------- server has no knowledge of configuration structure or model
    
            private static Dictionary<string, string> storage;
    
            private static void SaveConfigurationa(string appName, string SectionName, string payload, string enumForHierarchyLevel = null)
            {
                // transformer
                var section = string.Format("{0}.{1}", appName, SectionName);
                var data = (JObject)JsonConvert.DeserializeObject(payload);
                var keyValueData = Flatten(data, section);
    
                // check if user has permission for level overrides
                // store with proper overides
    
                // store the flat list in sql or data 
                //| KEY |           |Value|            |OverrideType| - default,sysadmin,appadmin,groups,user etc
                //app.section.Name, Rajnish
                //app.section.Address.Street, Oxley
                //app.section.Age, 18
    
                storage = keyValueData;
            }
    
            private static string GetConfiguration(string appName, string SectionName, string samplePayload)
            {
                var section = string.Format("{0}.{1}", appName, SectionName);
                var data = (JObject)JsonConvert.DeserializeObject(samplePayload);
                var keyValueSample = Flatten(data, section);
                // update data from sql or data store
                // apply property override rules and get value from overrides if exists
                var keyValueData = keyValueSample.Select(x => new KeyValuePair<string, string>(x.Key, storage[x.Key]));
    
                //read these
                //app.section.Name, Rajnish
                //app.section.Address.Street, Oxley
                //app.section.Age, 18
    
                UnFlatten(data, section, keyValueData);
    
                var formatedData = JsonConvert.SerializeObject(data);
                /*
                 * {
                      "Name": "Rajnish",
                      "Address": {
                        "Street": "Oxley"
                      },
                      "Age": "18"
                    }
                 * */
                return formatedData;
    
            }
            
            // Server side json helper
    
            private static void UnFlatten(JObject jsonObject, string prefix, IEnumerable<KeyValuePair<string, string>> data)
            {
                foreach (var item in data)
                {
                    var keyName = item.Key.Substring(prefix.Length + 1);
                    var storageValue = item.Value;
                    if (keyName.Contains("."))
                    {
                        var keys = keyName.Split('.');
                        var jtoken = (JToken)jsonObject;
                        foreach (var k in keys)
                        {
                            jtoken = jtoken.SelectToken(k);
                        }
                        ((JValue)jtoken).Value = storageValue;
                    }
                    else
                    {
                        jsonObject[keyName] = storageValue;
                    }
                }
            }
    
            private static Dictionary<string, string> Flatten(JObject jsonObject, string prefix)
            {
    
                IEnumerable jTokens = jsonObject.Descendants().Where(p => p.Count() == 0);
                Dictionary<string, string> results = jTokens.Aggregate(new Dictionary<string, string>(), (properties, jToken) =>
                {
                    properties.Add(string.Format("{0}.{1}", prefix, jToken.Path), jToken.ToString());
                    return properties;
                });
                return results;
            }
        }
    }