30 Nisan 2020

HTML Tablo da Genişletilebilir Satır

//
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
        integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">

    <style>
        .btnExp {
            border: 0px;
            background: transparent;
            font-weight: bold;
        }

        .hide {
            display: none;
        }

        .expBody {
            background-color: #f8f9fa;
            ;
        }
    </style>
</head>

<body>
    <table class="table expandableTable">
        <thead>
            <tr>
                <th scope="col">#</th>
                <th scope="col">First</th>
                <th scope="col">Last</th>
                <th scope="col">Handle</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <th scope="row">
                    <button type="button" class="btnExp">+</button>
                </th>
                <td>Mark</td>
                <td>Otto</td>
                <td>@mdo</td>
            </tr>
            <tr class="expBody hide">
                <td colspan="4">XXX</td>
            </tr>
            <tr>
                <th scope="row">
                    <button class="btnExp">+</button>
                </th>
                <td>Jacob</td>
                <td>Thornton</td>
                <td>@fat</td>
            </tr>
            <tr class="expBody hide">
                <td colspan="4">ZZZ</td>
            </tr>
            <tr>
                <th scope="row">
                    <button class="btnExp">+</button>
                </th>
                <td>Larry</td>
                <td>the Bird</td>
                <td>@twitter</td>
            </tr>
            <tr class="expBody hide">
                <td colspan="4">YYY</td>
            </tr>
        </tbody>
    </table>
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
        integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
        crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
        integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
        crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
        integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
        crossorigin="anonymous"></script>

    <script>
        function hasClass(ele, cls) {
            return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
        }

        function addClass(ele, cls) {
            if (!hasClass(ele, cls)) ele.className += " " + cls;
        }

        function removeClass(ele, cls) {
            if (hasClass(ele, cls)) {
                var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
                ele.className = ele.className.replace(reg, ' ');
            }
        }

        function expandableTable() {
            var expandableTables = document.getElementsByClassName('expandableTable');
            if (expandableTables != null) {
                for (var t = 0; t < expandableTables.length; t++) {
                    tt = expandableTables[t];
                    var expBtns = tt.getElementsByClassName('btnExp');
                    if (expBtns != null) {
                        for (var b = 0; b < expBtns.length; b++) {
                            var expBtn = expBtns[b];
                            expBtn.addEventListener('click', function (e) {
                                var btn = e.srcElement;
                                var _tr = btn.parentElement.parentElement.nextElementSibling;
                                if (btn.innerText == '-') {
                                    btn.innerText = '+';
                                    addClass(_tr,'hide');
                                } else {
                                    btn.innerText = '-';
                                    removeClass(_tr,'hide');
                                }
                            }, false);
                        }
                    }
                }
            }
        }
        expandableTable();
    </script>
</body>
</html>
//

7 Ocak 2020

Javascript Table To CSV

function isTable(element) {
    return (element.tagName == 'TABLE' || element.tagName == 'table')
}
function downloadCsv(csv, filename) {
    if (window.Blob == undefined
        || window.URL == undefined
        || window.URL.createObjectURL == undefined) {
        alert("Your browser doesn't support Blobs");
        return;
    }
    var BOM = "\uFEFF";
    var csvFile = new Blob([ BOM + csv], { type: "text/csv;" });
    var downloadLink = document.createElement("a");
    downloadLink.download = filename;
    downloadLink.href = window.URL.createObjectURL(csvFile);
    downloadLink.style.display = "none";
    document.body.appendChild(downloadLink);
    downloadLink.click();
}

function exportToCsv(id, filename, delimiter = ';') {
    tbl = document.getElementById(id);
    if (tbl != null && isTable(tbl)) {
        var rowArr = [];
        for (var j = 0; j < tbl.rows.length; j++) {
            var r = tbl.rows[j];
            var colArr = [];
            for (i = 0; i < r.cells.length; i++) {
                var c = r.cells[i];
                colArr.push(c.innerText);
            }
            rowArr.push(colArr.join(delimiter))
        }
    }
    downloadCsv(rowArr.join('\n'), filename);
}

2 Ocak 2020

Javascript DateTime To Formatted String

function dateToFormat(date, template) { var t = template; var day = date.getDate(); if (t.indexOf('dd') > -1) { if (day < 10) day = `0${day}`; t = t.replace('dd', day); } else t = t.replace('d', day); var month = date.getMonth() + 1; if (t.indexOf('MM') > -1) { if (month < 10) month = `0${month}`; t = t.replace('MM', month); } else t = t.replace('M', month); var year = date.getFullYear(); if (t.indexOf('yyyy') > -1) t = t.replace('yyyy', year); else if (t.indexOf('yyy') > -1) t = t.replace('yyy', `${year}`.substring(1, 4)); else if (t.indexOf('yy') > -1) t = t.replace('yy', `${year}`.substring(2, 4)); else if (t.indexOf('y') > -1) t = t.replace('y', `${year}`.substring(3, 4)); var hour = date.getHours(); if (t.indexOf('HH') > -1) { if (hour < 10) hour = `0${hour}`; t = t.replace('HH', hour); } else t = t.replace('H', hour); var min = date.getMinutes(); if (t.indexOf('mm') > -1) { if (min < 10) min = `0${min}`; t = t.replace('mm', min); } else t = t.replace('m', min); var sec = date.getSeconds(); if (t.indexOf('ss') > -1) { if (sec < 10) sec = `0${sec}`; t = t.replace('ss', sec); } else t = t.replace('s', sec); return t; }

19 Aralık 2019

Enum İçin Validation

//
public class DefinedEnumAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value != null)
        {
            if (Enum.IsDefined(value.GetType(), value))
            {
                return ValidationResult.Success;
            }
            else
            {
                return new ValidationResult($"Not valid enum type {value.GetType().Name}.");
            }
        }
        return new ValidationResult("" + validationContext.DisplayName + " is required");
    }
}
public enum OrderStatus
{
    OrderReceived = 0,
    Preparing = 1,
    Printing = 2,
    Ready = 3,
    Shipped = 4
}
public class OrderDto
{
    [DefinedEnum]
    public OrderStatus OrderStatus { get; set; }

}
//

21 Ekim 2019

C# ISO Oluşturma

DiscUtils
using DiscUtils.Iso9660;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace FileCount
{
    class Program
    {
        static void Main(string[] args)
        {
            string directoryPath = @"D:\test\";
            CreateIso("test", @"C:\Users\developer\Desktop\test.iso", directoryPath, new string[] { directoryPath });
            Console.ReadKey();
        }

        public static List<string> GetAllFiles(string directoryPath)
        {
            var result = new List<string>();
            if (Directory.Exists(directoryPath))
            {
                result.AddRange(Directory.GetFiles(directoryPath));
                foreach (var dir in Directory.GetDirectories(directoryPath))
                {
                    result.AddRange(GetAllFiles(dir));
                }
            }
            return result;
        }
        static string GetSubName(string rootDirectory, string path)
        {
            if (!path.StartsWith(rootDirectory))
                new ArgumentException("Given parameters are not in same root directory!");
            var output = path.Substring(rootDirectory.Length);
            if (output[0] == '\\')
                output = output.Substring(1);
            return output;
        }
        static void CreateIso(string volumeIdentifier, string output, string rootDirectory, string[] paths)
        {
            var builder = new CDBuilder();
            builder.UseJoliet = true;
            builder.VolumeIdentifier = volumeIdentifier;
            if (!Directory.Exists(rootDirectory))
                throw new DirectoryNotFoundException("The directory not found: " + rootDirectory);

            if (!paths.All(q => q.StartsWith(rootDirectory)))
                new ArgumentException("Given parameters are not in same root directory!");
            var files = new List<string>();
            foreach (var path in paths)
            {
                var fileAttr = File.GetAttributes(path);
                if (fileAttr.HasFlag(FileAttributes.Directory))

                    files.AddRange(GetAllFiles(path));
                else files.Add(path);
            }
            foreach (var file in files.Distinct())
            {
                builder.AddFile(GetSubName(rootDirectory, file), File.ReadAllBytes(file));
            }
            builder.Build(output);
        }
        
    }
}

2 Ekim 2019

Setting Config Örneği

public class CofigurationAttribute:Attribute
    {
        public string Name { getset; }
    }
 public static class Settings
    {
        const string settingFile = "Signator.config";
        private static XDocument configuration;
        private static void LoadConfigFile()
        {
            Logger.Info($"Settings are loading from {settingFile}.");
            if (configuration == null)
                configuration = XDocument.Load(settingFile);
        }
 
        private static void LoadSettings()
        {
            LoadConfigFile();
            foreach (var property in typeof(Settings).GetProperties().Where(q => q.CustomAttributes.Any(p => p.AttributeType.Name == "CofigurationAttribute")))
            {
                Logger.Info($"Setting is reading (${property.Name})... ");
                ReadConfigFile(property);
                Logger.Info($"Setting setted ({property.Name} = {property.GetValue(null)})... ");
            }
            Logger.Info($"Settings have been readen.");
        }
        private static void ReadConfigFile(PropertyInfo property)
        {
            var custom = property.CustomAttributes.FirstOrDefault(q => q.AttributeType.Name == "CofigurationAttribute");
            var name = custom.NamedArguments.SingleOrDefault(q => q.MemberName == "Name").TypedValue.Value.ToString();
            var element = configuration.Root.Element(name);
            property.SetValue(nullelement.Value);
        }
        public static void Initialize()
        {
            Logger.Info("Settings.Initialize is running");
            LoadSettings();
            CheckForSettings();
        }
 
        
 
        private static string SetPhysicalPath(string path)
        {
            if (string.IsNullOrWhiteSpace(path))
                throw new ArgumentNullException("");
            else if (path.Length > 1 & path[1== ':')
                return path;
            else
                return Path.Combine(RootDir, path);
        }
 
 
        private static Logger m_Logger = null;
        public static Logger Logger {
            get {
                if (m_Logger == null)
                    m_Logger = LogManager.GetLogger("session");
                return m_Logger;
            }
        }
        [Cofiguration(Name = "root_directory")]
        public static string RootDir { getprivate set; }
 
        private static string m_LicenseFile = string.Empty;
        [Cofiguration(Name = "license_file")]
        public static string LicenseFile {
            get { return m_LicenseFile; }
            set {
                m_LicenseFile = SetPhysicalPath(value);
            }
        }
 
 
        private static string m_XmlSignatureConfigFile;
        [Cofiguration(Name = "xml_signature_config_file")]
        public static string XmlSignatureConfigFile {
            get { return m_XmlSignatureConfigFile; }
            set {
                m_XmlSignatureConfigFile = SetPhysicalPath(value);
            }
        }
 
 
        private static string m_SignatureOutDirectory;
        [Cofiguration(Name = "signature_out_directory")]
        public static string SignatureOutDirectory {
            get { return m_SignatureOutDirectory; }
            set {
                m_SignatureOutDirectory = SetPhysicalPath(value);
            }
        }
   }
}

8 Ağustos 2019

C# Dinamik Kod Üretimi

System.Reflection.Emit namespace, metadata ve runtime sırasında IL oluşturmak için sınıflar içerir.
Bir DynamicMethod  ve ilişkili IL garbage-collector tarafından referans olarak verilmediği zaman toplanır. Yani belleği doldurmadan dinamik olarak methodlar oluşturup durabilirsiniz.

DynamicMethod Örneği:

static void Main()
        {
            var dynMeth = new DynamicMethod("Foo", null, null, typeof(Program));
            ILGenerator gen = dynMeth.GetILGenerator();
            gen.EmitWriteLine("Hello World");
            gen.Emit(OpCodes.Ret);
            dynMeth.Invoke(null, null);

        }

Method her zaman OpCodes.Ret ile biter. Return anlamına gelir.
EmitWriteLine  metodu ILGenerator da bir dizi düşük seviyedeki opcode ları yayınlayan kısayoldur.

Aynı sonucu Emit WriteLine ile alamak için aşağıda ki gibi kodu değiştirebiliriz.

 dynMeth = new DynamicMethod("Bar", null, null, typeof(Program));
gen = dynMeth.GetILGenerator();
MethodInfo mi = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });
gen.Emit(OpCodes.Ldstr, "Hello World2");
gen.Emit(OpCodes.Call, mi);
gen.Emit(OpCodes.Ret);
dynMeth.Invoke(null,null);


Public olmayan methodlara ulaşmamız için örnek:

var dynMeth = new DynamicMethod("Tar", null, null, typeof(Program));
ILGenerator gen = dynMeth.GetILGenerator();
MethodInfo privateMethod = typeof(Program).GetMethod("HelloWorld", BindingFlags.NonPublic | BindingFlags.Static);   
gen.Emit(OpCodes.Call, privateMethod);
gen.Emit(OpCodes.Ret);
dynMeth.Invoke(null, null);

Parametre ile Toplama İşlemi

using System;
using System.Reflection.Emit;

namespace ConsoleApp2
{
    class Program
    {
        delegate int BinaryFunction(int n1, int n2);
        static void Main()
        {

            var dynMeth = new DynamicMethod("Sum",
                typeof(int), //Return Type = int
                new[] { typeof(int), typeof(int) }, // Parameter Types = int, int
                typeof(Program));
            ILGenerator gen = dynMeth.GetILGenerator();
            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Ldarg_1);
            gen.Emit(OpCodes.Add);
            gen.Emit(OpCodes.Ret);

            // Usage 1
            var result = (int)dynMeth.Invoke(null, new object[] { 4, 5 });
            Console.WriteLine(result);
            
            //Usage 2 // Comman Way
            BinaryFunction sumCommonWay = (BinaryFunction)dynMeth.CreateDelegate(typeof(BinaryFunction));
            result = sumCommonWay(3, 4);
            Console.WriteLine(result);

           
            Console.ReadKey();
        }

    }
}



// Yerel Değişken Ekleme ve Döngüler 
using System;
using System.Reflection.Emit;

namespace ConsoleApp2
{
    class Program
    {
        static void Main()
        {
            var dynMeth = new DynamicMethod("Sum4", typeof(int), new[] { typeof(int) }, typeof(Program));
            ILGenerator gen = dynMeth.GetILGenerator();
            Label startLoop = gen.DefineLabel(); // Declare labels
            Label endLoop = gen.DefineLabel();

            LocalBuilder i = gen.DeclareLocal(typeof(int)); // int i for index
            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Stloc, i);

            LocalBuilder sum = gen.DeclareLocal(typeof(int)); // int sum for from 0 to i initial value
            gen.Emit(OpCodes.Ldc_I4,0);
            gen.Emit(OpCodes.Stloc, sum); // set value for local sum

            gen.MarkLabel(startLoop);

            gen.Emit(OpCodes.Ldc_I4, 1); // Load 10 onto eval stack
            gen.Emit(OpCodes.Ldloc, i); // Load x onto eval stack
            gen.Emit(OpCodes.Bgt, endLoop); // if (x > 10) goto endLoop


            gen.Emit(OpCodes.Ldloc, i); // Load x onto eval stack
            gen.Emit(OpCodes.Ldloc, sum); // Load x onto eval stack
            gen.Emit(OpCodes.Add);
            gen.Emit(OpCodes.Stloc, sum); // Save result back to x

            gen.Emit(OpCodes.Ldloc, i); // Load x onto eval stack
            gen.Emit(OpCodes.Ldc_I4,  -1); // Load -1 onto the stack
            gen.Emit(OpCodes.Add); // Add them together
            gen.Emit(OpCodes.Stloc, i); // Save result back to x
           

            gen.Emit(OpCodes.Br, startLoop); // return to start of loop
            gen.MarkLabel(endLoop);
            gen.Emit(OpCodes.Ldloc, sum); //
            gen.Emit(OpCodes.Ret);

            var res = (int)dynMeth.Invoke(null, new object[] { 15 });

            Console.WriteLine(res);
            Console.ReadKey();
        }

    }
}






7 Ağustos 2019

PipeStream

using System;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2
{
    class Program
    {
        /*
         
         PipeStream
         .Net 3.5 ile çıkmıştır. Bir işlemin diğer işlemlerle Windows pipes protokolü üzerinden haberleşmesini sağlar.

         İki çeşittir.
         * Anonymous pipe (daha hızlı)
            Aynı bilgisiyarda ki parnet ve child işlemleri için tek yönlü haberleşmesini sağlar.
         * Named pipe (daha esnek):
            Aynı bilgisayarda ki veya aynı Windows ağındaki farklı bilgisayarlar arasında ki keyfi işlemler arasında çift yönlü haberleşmesini sağlar.

        Bir tek bilgisayar üzerinde ki IPC(interprocess communication) haberleşme için pipe kullanmak uygundur.       

             */


        static void Main(string[] args)
        {
            //NamedPipeServerExample();
            AnonymousPipeServerExample();
            Console.ReadKey();
        }

        /*Named Pipes
         Named pipes ile taraflar aynı isim üzerinden doğrudan haberleşir. Protokol iki farklı rol tanımlar: Client ve Server
         Client ve Server arasında ki haberleşme aşağıdaki gibidir.
         NamedPipeServerStream ile server örneği oluşturulur ve WaitForConnection methodu çağrılır.
         NamedPipeClientStream ile client oluşturulur ve Connect ile bağlanılır.
         */

        static byte[] ReadMessage(PipeStream stream)
        {
            using (var ms = new MemoryStream())
            {
                var buffer = new Byte[0x1000]; // Read in 4KB blocks
                do
                {
                    ms.Write(buffer, 0, stream.Read(buffer, 0, buffer.Length));
                } while (!stream.IsMessageComplete);
                return ms.ToArray();
            }
        }

        static void NamedPipeServerExample()
        {
            string serverName = "pipedream";

            Task.Factory.StartNew(() =>
            {
                using (var server = new NamedPipeServerStream(serverName, PipeDirection.InOut, 1, PipeTransmissionMode.Message))
                {
                    server.WaitForConnection();
                    byte[] msg = Encoding.UTF8.GetBytes("Hello");
                    server.Write(msg, 0, msg.Length);
                    var resp = Encoding.UTF8.GetString(ReadMessage(server));
                    Console.WriteLine(resp);
                }
            });
            Task.Factory.StartNew(() =>
            {
                using (var client = new NamedPipeClientStream(serverName))
                {
                    client.Connect();
                    client.ReadMode = PipeTransmissionMode.Message;
                    var rec = Encoding.UTF8.GetString(ReadMessage(client));
                    Console.WriteLine(rec);
                    var msg = Encoding.UTF8.GetBytes("Hello right back!");
                    client.Write(msg, 0, msg.Length);
                }
            });
        }


        /*Anonymous pipes
         Anonymous pipe parent ve child arasında ki iki işlem arasında tek yönlü bir haberleşme sağlar.
         System çapıda isim kullanmak yerine doğrudan private handle üzerinden ayarlanır.

        1. Server AnonymousPipeServerStream örneği oluşturulur, PipeDirection In ve Out şeklinde belirtilir.
        2. Server GetClientHandleAsString ile pipe'ın kimliğini çağırırız k bunu clienta göndereceğiz.(Client oluşturulurken parametre olarak vereceğiz.)
        3. child process AnonymousPipeClientStream PipeDirection un karşıtı olarak girilir.
        4. server 2. adımda üretilen yerel handle i serbest bırakmak için DisposeLocalCopyOfClientHandle metodunu çağırırız.
        5. parent ve child processler birbirileri ile writing ve reading ile çalışır.
         */

        static void AnonymousPipeServerExample()
        {
            string clientExe = @"C:\Users\developer\Source\repos\ConsoleApp1\ClientDemo\bin\Debug\ClientDemo.exe";
            HandleInheritability inherit = HandleInheritability.Inheritable;
            using (var tx = new AnonymousPipeServerStream(PipeDirection.Out, inherit))
            using (var rx = new AnonymousPipeServerStream(PipeDirection.In, inherit))
            {
                string txID = tx.GetClientHandleAsString();
                string rxID = rx.GetClientHandleAsString();
                var startInfo = new ProcessStartInfo(clientExe, txID + " " + rxID);
                startInfo.UseShellExecute = false; // Required for child process
                Process p = Process.Start(startInfo);
                tx.DisposeLocalCopyOfClientHandle(); // Release unmanaged
                rx.DisposeLocalCopyOfClientHandle(); // handle resources.
                tx.WriteByte(100);
                Console.WriteLine("Server received: " + rx.ReadByte());
                p.WaitForExit();
            }
        }       
    }
}

///////////////
using System;
using System.IO.Pipes;

namespace ClientDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            var rxID = args[0];
            var txID = args[1];
            using (var rx = new AnonymousPipeClientStream(PipeDirection.In, rxID))
            using (var tx = new AnonymousPipeClientStream(PipeDirection.Out, txID))
            {
                Console.WriteLine("Client received: " + rx.ReadByte());
                tx.WriteByte(200);
            }

        }
    }
}


1 Ağustos 2019

Memory Mapped Files in .NET

Non-Persisted Memory Mapped Files


using System;
using System.IO.MemoryMappedFiles;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
       
            using (MemoryMappedFile memoryMappedFile = MemoryMappedFile.CreateNew("idg.txt", 5))
            {
                using (MemoryMappedViewAccessor memoryMappedViewAccessor = memoryMappedFile.CreateViewAccessor())
                {
                    memoryMappedViewAccessor.Write(0,1);
                    Console.ReadKey();

                    memoryMappedViewAccessor.Dispose();

                    memoryMappedFile.Dispose();
                }
            }

        }
    }
}

using System;
using System.IO.MemoryMappedFiles;
using System.Threading;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var x = 0;

            using (MemoryMappedFile memoryMappedFile = MemoryMappedFile.OpenExisting("idg.txt"))
            using (MemoryMappedViewAccessor memoryMappedViewAccessor = memoryMappedFile.CreateViewAccessor())
            {
                while (true)
                {
                    var t = memoryMappedViewAccessor.ReadInt32(0);
                    if (x != t)
                    {
                        x = t;
                        Console.WriteLine(t);
                    }
                    Thread.Sleep(1);
                }
            }
        }
    }
}
Kaynak:
https://www.infoworld.com/article/2898365/working-with-memory-mapped-files-in-net.html
https://www.buraksenyurt.com/post/Persisted-Memory-Mapped-Files
https://docs.microsoft.com/tr-tr/dotnet/standard/io/memory-mapped-files

2 Nisan 2019

Multipart Form Post In C#

using System;
using System.Collections.Generic;
using System.IO;

namespace SampleProject.MultipartFormData
{
    /// <summary>
    /// Extension methods for generic dictionaries.
    /// </summary>
    public static class DictionaryExtensions
    {
        /// <summary>
        /// Template for a multipart/form-data item.
        /// </summary>
        public const string FormDataTemplate = "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}\r\n";

        /// <summary>
        /// Writes a dictionary to a stream as a multipart/form-data set.
        /// </summary>
        /// <param name="dictionary">The dictionary of form values to write to the stream.</param>
        /// <param name="stream">The stream to which the form data should be written.</param>
        /// <param name="mimeBoundary">The MIME multipart form boundary string.</param>
        /// <exception cref="System.ArgumentNullException">
        /// Thrown if <paramref name="stream" /> or <paramref name="mimeBoundary" /> is <see langword="null" />.
        /// </exception>
        /// <exception cref="System.ArgumentException">
        /// Thrown if <paramref name="mimeBoundary" /> is empty.
        /// </exception>
        /// <remarks>
        /// If <paramref name="dictionary" /> is <see langword="null" /> or empty,
        /// nothing wil be written to the stream.
        /// </remarks>
        public static void WriteMultipartFormData(
          this Dictionary<string, string> dictionary,
          Stream stream,
          string mimeBoundary)
        {
            if (dictionary == null || dictionary.Count == 0)
            {
                return;
            }
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }
            if (mimeBoundary == null)
            {
                throw new ArgumentNullException("mimeBoundary");
            }
            if (mimeBoundary.Length == 0)
            {
                throw new ArgumentException("MIME boundary may not be empty.", "mimeBoundary");
            }
            foreach (string key in dictionary.Keys)
            {
                string item = String.Format(FormDataTemplate, mimeBoundary, key, dictionary[key]);
                byte[] itemBytes = System.Text.Encoding.UTF8.GetBytes(item);
                stream.Write(itemBytes, 0, itemBytes.Length);
            }
        }
    }
}




/////////////////////


using System;
using System.IO;
using System.Text;

namespace SampleProject.MultipartFormData
{
    /// <summary>
    /// Extension methods for <see cref="System.IO.FileInfo"/>.
    /// </summary>
    public static class FileInfoExtensions
    {
        /// <summary>
        /// Template for a file item in multipart/form-data format.
        /// </summary>
        public const string HeaderTemplate = "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\"\r\nContent-Type: {3}\r\n\r\n";

        /// <summary>
        /// Writes a file to a stream in multipart/form-data format.
        /// </summary>
        /// <param name="file">The file that should be written.</param>
        /// <param name="stream">The stream to which the file should be written.</param>
        /// <param name="mimeBoundary">The MIME multipart form boundary string.</param>
        /// <param name="mimeType">The MIME type of the file.</param>
        /// <param name="formKey">The name of the form parameter corresponding to the file upload.</param>
        /// <exception cref="System.ArgumentNullException">
        /// Thrown if any parameter is <see langword="null" />.
        /// </exception>
        /// <exception cref="System.ArgumentException">
        /// Thrown if <paramref name="mimeBoundary" />, <paramref name="mimeType" />,
        /// or <paramref name="formKey" /> is empty.
        /// </exception>
        /// <exception cref="System.IO.FileNotFoundException">
        /// Thrown if <paramref name="file" /> does not exist.
        /// </exception>
        public static void WriteMultipartFormData(
          this FileInfo file,
          Stream stream,
          string mimeBoundary,
          string mimeType,
          string formKey)
        {
            if (file == null)
            {
                throw new ArgumentNullException("file");
            }
            if (!file.Exists)
            {
                throw new FileNotFoundException("Unable to find file to write to stream.", file.FullName);
            }
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }
            if (mimeBoundary == null)
            {
                throw new ArgumentNullException("mimeBoundary");
            }
            if (mimeBoundary.Length == 0)
            {
                throw new ArgumentException("MIME boundary may not be empty.", "mimeBoundary");
            }
            if (mimeType == null)
            {
                throw new ArgumentNullException("mimeType");
            }
            if (mimeType.Length == 0)
            {
                throw new ArgumentException("MIME type may not be empty.", "mimeType");
            }
            if (formKey == null)
            {
                throw new ArgumentNullException("formKey");
            }
            if (formKey.Length == 0)
            {
                throw new ArgumentException("Form key may not be empty.", "formKey");
            }
            string header = String.Format(HeaderTemplate, mimeBoundary, formKey, file.Name, mimeType);
            byte[] headerbytes = Encoding.UTF8.GetBytes(header);
            stream.Write(headerbytes, 0, headerbytes.Length);
            using (FileStream fileStream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read))
            {
                byte[] buffer = new byte[1024];
                int bytesRead = 0;
                while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                {
                    stream.Write(buffer, 0, bytesRead);
                }
                fileStream.Close();
            }
            byte[] newlineBytes = Encoding.UTF8.GetBytes("\r\n");
            stream.Write(newlineBytes, 0, newlineBytes.Length);
        }
    }
}



//////////////////




using SampleProject.MultipartFormData;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;

namespace SampleProject
{
    public class HttpRequestFormDataDemo
    {
       

        private static string BasicAuthorization(string username, string password)
        {
            var encoded = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));
            return "Basic " + encoded;
        }


        const string host = "example.com";
        const string serviceUrl = "https://example.com";
        public static string SampleMethodMultipleFormData(string clientUsername, string clientPassword, string serviceUsername, string servicePassword, string scope)
        {
            var url = serviceUrl + "/connect/token";

            var boundary = new string('-', 16) + DateTime.Now.Ticks.ToString();
            var request = HttpWebRequest.CreateHttp(url);

            ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
            request.Method = "POST";
            request.Headers.Add("Authorization", BasicAuthorization(clientUsername, clientPassword));
            request.Accept = "application/json";
            request.Host = host;

            request.ContentType = "multipart/form-data; boundary=" + boundary;


            var postData = new Dictionary<string, string>();
            postData["grant_type"] = "password";
            postData["username"] = serviceUsername;
            postData["password"] = servicePassword;
            postData["scope"] = scope;

            var requestStream = request.GetRequestStream();

            postData.WriteMultipartFormData(requestStream, boundary);
            byte[] endBytes = Encoding.UTF8.GetBytes("--" + boundary + "--");
            requestStream.Write(endBytes, 0, endBytes.Length);
            requestStream.Close();
            using (var response = request.GetResponse())
            using (var reader = new StreamReader(response.GetResponseStream()))
            {
                return reader.ReadToEnd();
            };            
        }
    }
}
Alıntıdır. Orjinali için https://www.paraesthesia.com/archive/2009/12/16/posting-multipartform-data-using-.net-webrequest.aspx/