csharp Azure事件中心

general docs.md
Event Hubs is a big data streaming platform and event ingestion service.

Event Hubs represents the "front door" for an event pipeline, often called an event ingestor in solution architectures.
An event ingestor is a component or service that sits between event publishers and event consumers to decouple the production 
of an event stream from the consumption of those events.

Data sent to an event hub can be transformed and stored by using any 
real-time analytics provider or batching/storage adapters.

Scenarios:
- Anomaly detection (fraud/outliers)
- Application logging
- Analytics pipelines, such as clickstreams
- Live dashboarding
- Archiving data
- Transaction processing
- User telemetry processing
- Device telemetry streaming

# Why use Event Hubs?

- Easy way to process and get timely insights from data sources.
- Event Hubs is a fully managed PaaS.
- Support for real-time and batch processing.
- Grow to gigabytes or terabytes.

# Key architecture components
- Event producers: sends data to an event hub - HTTPS or AMQP 1.0 or Apache Kafka.
- Partitions: consumers only read a partition of the stream.
- Consumer groups: A view of a hub. Reads the stream independently at own pace.
- Throughput units: Pre-purchased units of capacity.
- Event receivers: Reads event data from an event hub via AMQP 1.0 session.

![components](https://docs.microsoft.com/en-us/azure/event-hubs/media/event-hubs-about/event_hubs_architecture.png)

# Structure

## Publishing

Event Hubs ensures that all events sharing a partition key value are delivered in order, and to the same partition.

Each publisher uses its own unique identifier when publishing events to an event hub, using the following mechanism:
```HTTP
//[my namespace].servicebus.windows.net/[event hub name]/publishers/[my publisher name]
```

When using publisher policies, the `PartitionKey` value is set to the publisher name.

## Capture

Automatically capture streaming data and save it to choice of Blob storage account, or Data Lake Service account.

## Partitions

Message streaming through partitioned consumer pattern - each consumer only reads a specific partition of the stream.

Partition is an ordered sequence of events.
New events are added to the end of this sequence.
A partition can be thought of as a "commit log."
send messages.cs
var connectionStringBuilder = new EventHubsConnectionStringBuilder("Endpoint=sb://ric01ehub.servicebus.windows.net/;SharedAcc...")
{
    EntityPath = "ric01hub01"
};

private EventHubClient eventHubClient = EventHubClient.CreateFromConnectionString(connectionStringBuilder.ToString());

\!h await eventHubClient.SendAsync(new EventData(Encoding.UTF8.GetBytes("Some message")));

receive messages.cs
var eventProcessorHost = new EventProcessorHost(
    "ric01hub01", // hub name
    PartitionReceiver.DefaultConsumerGroupName,
    EventHubConnectionString,
    StorageConnectionString,
    StorageContainerName);

// Registers the Event Processor Host and starts receiving messages
await eventProcessorHost.RegisterEventProcessorAsync<SimpleEventProcessor>();

public class SimpleEventProcessor : IEventProcessor
{
    public Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages)
    {
        foreach (var eventData in messages)
        {
            var data = Encoding.UTF8.GetString(eventData.Body.Array, eventData.Body.Offset, eventData.Body.Count);
            Console.WriteLine($"Message received. Partition: '{context.PartitionId}', Data: '{data}'");
        }
        return context.CheckpointAsync();
    }
    // other methods ProcessErrorAsync, OpenAsync, CloseAsync
}

csharp Asynch文件上传器

如果您正在使用更新面板或sime ajax妨碍标准文件上传器,并且您无法将文件加载到控件中,请改用它。它将方法绑定到上传文件时触发的上传事件。然后使用它将文件写入磁盘。

.cs
<!--In your markup -->
  <ajaxToolkit:AsyncFileUpload runat="server" ID="fuLogoUploader" OnUploadedComplete="AsyncUpload_UploadedComplete" />
  
  // In your code behind
  
    protected void AsyncUpload_UploadedComplete(object sender, EventArgs e)
    {
        var fileLocation =
            FileHelper.GetFullFilePhysicalPath(SettingsKeyInfoProvider.GetValue(
                "LogoUploadLocation",
                SiteContext.CurrentSiteName),
                null);

        var fileUploadEventArgs = e as AsyncFileUploadEventArgs;
        var fileUploader = sender as AsyncFileUpload;

        if (fileUploader.HasFile)
            SaveImageToDisk(fileUploader, fileLocation, fileUploadEventArgs);
    }

csharp 通知中心

General docs.md
# General

A multi-platform, scalable push-notification engine.

Targets iOS, Android, Windows, Kindle, Baidu, etc.

Back-ends: cloud or on-premises.

# Platform Notification Systems

Push notifications delivered through platform-specific infrastructures 
called Platform Notification Systems (PNSs). 

To send a notification to all customers across the Android, iOS, and 
Windows versions of an app, the developer must work with 
Apple Push Notification Service (APNS), 
Firebase Cloud Messaging (FCM), and 
Windows Notification Service (WNS) separately.

![notifications](https://docs.microsoft.com/en-us/azure/notification-hubs/media/notification-hubs-overview/notification-hub-diagram.png)

# Why Notification Hub

- Eliminates all complexities associated with pushing 
notifications on your own from your app backend.
- Support for all major push platforms.
- Common interface to push to all platforms.
- .NET, Node.js, Java, Python, etc.
- Rich set of delivery patterns
  - Broadcast to one or multiple platforms
  - Push to device
  - Push to user
  - Push to segment with dynamic tags
  - Localized push
  - Silent push
  - Scheduled push
  - Direct push
  - Personalized push

windows app listen.cs
var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
var hub = new NotificationHub("[HubName]", "[DefaultListenSharedAccessSignature]");
var result = await hub.RegisterNativeAsync(channel.Uri);

// Displays the registration ID so you know it was successful
if (result.RegistrationId != null)
{
    var dialog = new MessageDialog("Registration successful: " + result.RegistrationId);
    dialog.Commands.Add(new UICommand("OK"));
    await dialog.ShowAsync();
}
send push.cs
var nhClient = NotificationHubClient.CreateClientFromConnectionString("ConnectionString", "HubName");

// Register fake device - Firebase
var fcmDeviceId = Guid.NewGuid().ToString();
var fcmInstallation = new Installation
{
    InstallationId = "fake-fcm-install-id",
    Platform = NotificationPlatform.Fcm,
    PushChannel = fcmDeviceId,
    PushChannelExpired = false,
    Tags = new[] { "fcm" }
};
await nhClient.CreateOrUpdateInstallationAsync(fcmInstallation);

// Broadcast
var outcomeFcm = await nhClient.SendFcmNativeNotificationAsync(FcmSampleNotificationContent);

csharp 启动外部流程

有时,只需按一下按钮就可以启动某个过程,或者像这样。

initExtProcess
public static bool initNewProcess()
        {
            string pathToExe = @"\\path\to\exe";
            elapsedTime = 0;
            eventHandled = false;

            using (myProcess = new Process())
            {
                try
                {
                    // Start a process to print a file and raise an event when done.

                    SecureString theSecureString = new NetworkCredential("", AppSettings.Get<string>("SYSTEM.PASSWORD")).SecurePassword;

                    if (File.Exists(pathToExe))
                    {
                        ProcessStartInfo wic = new ProcessStartInfo(pathToExe);
                        wic.Arguments = "0";
                        wic.UserName = AppSettings.Get<string>("SYSTEM.DOMAIN");
                        wic.UserName = AppSettings.Get<string>("SYSTEM.USERNAME");
                        wic.Password = theSecureString;
                        wic.UseShellExecute = false;
                        var startWIC = Process.Start(wic);
                        startWIC.EnableRaisingEvents = true;
                        startWIC.Exited += new EventHandler(myProcess_Exited);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                    //throw new Exception($"An error occurred trying to print \"{pathToExe}\":\n{ex.Message}");
                    return false;
                }

                // Wait for Exited event, but not more than 30 seconds.
                const int SleepAmount = 100;
                while (!eventHandled)
                {
                    elapsedTime += SleepAmount;
                    if (elapsedTime > 30000)
                    {
                        break;
                    }

                    Thread.Sleep(SleepAmount);
                }
            }

            return true;
        }

csharp foreach DateTime

日期遍历

foreach
void Main()
{
    DateTime StartDate = DateTime.Parse("2019/01/01");
    DateTime EndDate = DateTime.Parse("2019/12/31");

    foreach (DateTime day in EachDay(StartDate, EndDate))
    {
        Console.WriteLine(day);
    }
}

public IEnumerable<DateTime> EachDay(DateTime from, DateTime thru)
{
    for(var day = from.Date; day.Date <= thru.Date; day = day.AddDays(1))
        yield return day;
}

csharp 达网络在如果看不到中做302跳转

global_302
        protected void Application_BeginRequest(object sender, EventArgs e)
        {
            string _url = Request.Path, _to = "http://baikang100.com";
            if (_url.Contains("/shop/")) {
                Response.Status = "302 Object Moved";
                Response.AppendHeader("Location", _to);
            }
        }

csharp 从XML反序列化

Cargamos un XML que o vieneporparámetrodelafunciónoun a pelo。 Luego,si es necesario pillamos en CDATA del XML y borramos la cabecera de CDATA。 Nos queda un XML donde lo serializamos con la clase Serializerqueestáelandadoamásabajo。 Deserializamos el XML con el objeto que对应一个结构化的XML。 Obtenemos un objeto con los valores del XML。

DeserializeFromXML
private static void DeserializeFromXML(string soapResult)
{
  //XDocument xDoc = XDocument.Parse(soapResult);
  XDocument xDoc = XDocument.Parse(@"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"">
             <soapenv:Body>
                <RespuestaAtex xmlns=""http://webservices.atex.consulta.vehiculos.servicios.trafico.es"" >
                   <idUsuario>11110101C</idUsuario>
                   <idOrganismoResponsable>11110101C</idOrganismoResponsable>
                   <idResponsable>11110101C</idResponsable>
                   <version>4</version>
                   <CriteriosConsultaVehiculo >
                      <matricula>0149HWC</matricula>
                   </CriteriosConsultaVehiculo>
                   <resultado>OK</resultado>
                   <respuesta><![CDATA[<?xml version=""1.0"" encoding=""ISO-8859-1""?><vehiculo><datosGenerales><descripcionVehiculo><bastidor>WAUZZZ4F49N056245</bastidor><marca><codigo>00143</codigo><descripcion>AUDI</descripcion></marca><modelo>A6</modelo><nive/><paisProcedencia/><servicio><codigo>B00</codigo><descripcion>PART - SIN ESPECIFICAR</descripcion></servicio><servicioComplementario/><tipoIndustria><codigo/><descripcion>NO DISPONIBLE</descripcion></tipoIndustria><tipoVehiculo><codigo>40</codigo><descripcion>TURISMO</descripcion></tipoVehiculo></descripcionVehiculo><domicilioVehiculo><calle>CLL CONRADO DEL CAMPO 101</calle><codPostal>03204</codPostal><municipio>ELCHE</municipio><provincia><codigo>A</codigo><descripcion>ALICANTE</descripcion></provincia><pueblo/></domicilioVehiculo><domicilioVehiculoIne><provincia/></domicilioVehiculoIne><fechasControl><fechaItv>2016 - 03 - 05T00: 00:00 + 01:00</fechaItv><fechaMatriculacion>2014 - 03 - 07T00: 00:00 + 01:00</fechaMatriculacion><fechaPrimeraMatriculacion>2009 - 04 - 28T00: 00:00 + 02:00</fechaPrimeraMatriculacion></fechasControl><indicadores><bajaDefinitiva/><bajaTemporal/><cargaEEFF/><embargo/><excesoPesoDimension/><importacion/><incidencias>S</incidencias><limitacionDisposicion/><posesion/><precinto/><puertoFranco/><reformas>N</reformas><renting>N</renting><subasta>N</subasta><sustraccion/><tutela/></indicadores><matriculacion><fechaMatriculacion>2014 - 03 - 07T00: 00:00 + 01:00</fechaMatriculacion><jefatura><codigo>A</codigo><descripcion>ALICANTE</descripcion></jefatura><matricula>0149HWC</matricula><sucursal><codigo>0</codigo><descripcion/></sucursal></matriculacion><servicioAutonomo/><titular><datosPersona><identificacionPFisica><indicadorDevPF>false</indicadorDevPF></identificacionPFisica><identificacionPJuridica><cif>B54083142</cif><indicadorDevPJ>false</indicadorDevPJ><razonSocial>PROYECTO FUTURO TRESCIENTOS SL</razonSocial></identificacionPJuridica><personaFisica><indicadorDevPF>false</indicadorDevPF></personaFisica><personaJuridica><cif>B54083142</cif><indicadorDevPJ>false</indicadorDevPJ><razonSocial>PROYECTO FUTURO TRESCIENTOS SL</razonSocial></personaJuridica></datosPersona><domicilio><calle>CL CONRADO DEL CAMPO 101</calle><codPostal>03204</codPostal><municipio>ELCHE</municipio><provincia><codigo>A</codigo><descripcion>ALICANTE</descripcion></provincia><pueblo/></domicilio><domicilioIne><provincia/></domicilioIne></titular><requisitoria/></datosGenerales><datosTecnicos><carroceria/><catHomologacion/><color><codigo/><descripcion>NO DISPONIBLE</descripcion></color><combustibleEmisiones><categoriaElectrica/><codigoEco/><codos>0.0</codos><ecoInnovacion/><nivelEmisiones/><propulsion><codigo>1</codigo><descripcion>DIESEL</descripcion></propulsion><reduccionEco/><tipoAlimentacion><codigo/><descripcion/></tipoAlimentacion></combustibleEmisiones><distancias/><documentos><periodoValidezTarjeta>0</periodoValidezTarjeta><periodoValidezTarjeta15>15</periodoValidezTarjeta15><periodoValidezTarjetaNoValida>2</periodoValidezTarjetaNoValida><periodoValidezTarjetaValida>1</periodoValidezTarjetaValida></documentos><fabricante/><masas><masaMaxTecnica>0</masaMaxTecnica><masaServicio>0</masaServicio><pesoMaximo>2365</pesoMaximo><tara>1735</tara></masas><numHomologacion/><plazas><mixtas>000</mixtas><normales>5</normales><numPlazasPie>0</numPlazasPie></plazas><potencias><cilindrada>2698.0</cilindrada><potenciaFiscal>18.74</potenciaFiscal><potenciaNetaMax>0.0</potenciaNetaMax><relPotenciaPeso>0.0</relPotenciaPeso></potencias><procedencia><codigo>3</codigo><descripcion>IMPORT.CEE</descripcion></procedencia><tipoItv/><variante/><version/><datosTarjetaItv/></datosTecnicos><datosResponsables/><datosTramites><listaRematriculaciones/><matriculacionTemporal><anotacion/><fecha> 2009 - 04 - 28T00: 00:00 + 02:00 </fecha><matriculaAnterior/></matriculacionTemporal></datosTramites><datosAdministrativos><listaAvisos/><listaDenegatorias/></datosAdministrativos><datosITVReformas><listaItvs><itv><anotacion>0</anotacion><cuentaHoras>0</cuentaHoras><estacion/><fechaCaducidad> 2016 - 03 - 05T00: 00:00 + 01:00</fechaCaducidad><kilometraje>0</kilometraje><motivoItv><codigo>M</codigo><descripcion>PREVIA MATRIC.</descripcion></motivoItv><provincia><codigo>A</codigo><descripcion>ALICANTE</descripcion></provincia><resultadoItv><codigo>F</codigo><descripcion>FAVORABLE</descripcion></resultadoItv></itv></listaItvs></datosITVReformas><datosSeguros><listaSeguros/></datosSeguros><listaVehiculos/><datosSeguridad><listaElementosSeguridad/><ncap><anioEnsayo>2004</anioEnsayo><adultos>5.0</adultos><menores>4.0</menores><peatones>1.0</peatones><seguridad>0.0</seguridad><global>0.0</global></ncap></datosSeguridad><datosLibroTaller><listaDetalleIncidencias/></datosLibroTaller></vehiculo>]]></respuesta>
                </RespuestaAtex>
             </soapenv:Body>
          </soapenv:Envelope>");
  var xcdata = xDoc.DescendantNodes().OfType<XCData>().FirstOrDefault();
  string xmlVeh = xcdata.ToString().Replace("<![CDATA[", "").Replace("]]>", "");

  Serializer ser = new Serializer();
  PolVehiculoATEX vehAtex = ser.Deserialize<PolVehiculoATEX>(xmlVeh);
}

public class Serializer
    {
        /// <summary>
        /// populate a class with xml data 
        /// </summary>
        /// <typeparam name="T">Object Type</typeparam>
        /// <param name="input">xml data</param>
        /// <returns>Object Type</returns>
        public T Deserialize<T>(string input) where T : class
        {
            System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(T));

            using (StringReader sr = new StringReader(input))
            {
                return (T)ser.Deserialize(sr);
            }
        }

        /// <summary>
        /// convert object to xml string
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ObjectToSerialize"></param>
        /// <returns></returns>
        public string Serialize<T>(T ObjectToSerialize)
        {
            XmlSerializer xmlSerializer = new XmlSerializer(ObjectToSerialize.GetType());

            using (StringWriter textWriter = new StringWriter())
            {
                xmlSerializer.Serialize(textWriter, ObjectToSerialize);
                return textWriter.ToString();
            }
        }
    }
        

csharp Azure Batch

docs.md
App / Service uploads input data files to Azure storage and then creates a pool of Batch compute nodes (virtual machines).

It then creates a job that runs tasks to process each input file on the pool.

![arch](https://docs.microsoft.com/en-us/azure/batch/media/batch-technical-overview/tech_overview_03.png)
create.sh
# Create resource group
az group create --name batch --location northeurope

# Create storage account
az storage account create \
    --resource-group batch \
    --name batchricstorageaccount \
    --location northeurope \
    --sku Standard_LRS

# Create batch account
az batch account create \
    --name ricbatchaccount \
    --storage-account batchricstorageaccount \
    --resource-group batch \
    --location northeurope

# To create and manage compute pools and jobs, you need to authenticate with Batch.
# Log in to the account with the az batch account login command.
# After you log in, your az batch commands use this account context.
az batch account login \
    --name ricbatchaccount \
    --resource-group batch \
    --shared-key-auth

# Create a pool of Linux compute nodes
az batch pool create \
    --id mypool \
    --vm-size Standard_A1_v2 \
    --target-dedicated-nodes 2 \
    --image canonical:ubuntuserver:16.04-LTS \
    --node-agent-sku-id "batch.node.ubuntu 16.04"

# To see the status of the pool
az batch pool show --pool-id mypool \
    --query "allocationState"

# Create a job
az batch job create \
    --id myjob \
    --pool-id mypool

# Create tasks
for i in {1..4}
do
   az batch task create \
    --task-id mytask$i \
    --job-id myjob \
    --command-line "/bin/bash -c 'printenv | grep AZ_BATCH; sleep 90s'"
done

# View task #1 status
az batch task show \
    --job-id myjob \
    --task-id mytask1

# View task #1 output
# To list the files created by a task on a compute node
az batch task file list \
    --job-id myjob \
    --task-id mytask1 \
    --output table

# To download one of the output files
az batch task file download \
    --job-id myjob \
    --task-id mytask1 \
    --file-path stdout.txt \
    --destination ./stdout.txt

# Clean up resources
# There is no charge for the Batch account itself.
# You are charged for pools while the nodes are running, even if no jobs are scheduled
# When you no longer need a pool, delete it (all task output on the nodes is deleted).
az batch pool delete --pool-id mypool
create using NET.cs
// From https://docs.microsoft.com/en-us/azure/batch/quick-run-dotnet

// Retrieve the storage account
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(storageConnectionString);
// Create the blob client
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

// Add files to process
CloudBlobContainer container = blobClient.GetContainerReference(containerName);
CloudBlockBlob blobData = container.GetBlockBlobReference(blobName);
blobData.UploadFromFileAsync(filePath).Wait();

// Create a BatchClient object to create and manage pools, jobs, and tasks in the Batch service
BatchSharedKeyCredentials cred = new BatchSharedKeyCredentials(BatchAccountUrl, BatchAccountName, BatchAccountKey);
using (BatchClient batchClient = BatchClient.Open(cred))
{
  // ...
}

// Create a Windows Server image, VM configuration, Batch pool
ImageReference imageReference = new ImageReference(
    publisher: "MicrosoftWindowsServer",
    offer: "WindowsServer",
    sku: "2016-datacenter-smalldisk",
    version: "latest"
);

VirtualMachineConfiguration vmConfiguration = new VirtualMachineConfiguration(
    imageReference: imageReference,
    nodeAgentSkuId: "batch.node.windows amd64"
);

CloudPool pool = batchClient.PoolOperations.CreatePool(
    poolId: "DotNetQuickstartPool",
    targetDedicatedComputeNodes: 2,
    virtualMachineSize: "STANDARD_A1_v2",
    virtualMachineConfiguration: vmConfiguration);
pool.Commit();

// Create a Batch job
CloudJob job = batchClient.JobOperations.CreateJob();
job.Id = "DotNetQuickstartJob";
job.PoolInformation = new PoolInformation { PoolId = "DotNetQuickstartPool" };
job.Commit();

// Create a task to process each of the input files (uploaded to blob storage earlier)
string taskId = String.Format("Task{0}", i);
string inputFilename = inputFiles[i].FilePath;
string taskCommandLine = String.Format("cmd /c type {0}", inputFilename);
CloudTask task = new CloudTask(taskId, taskCommandLine);
task.ResourceFiles = new List<ResourceFile> { inputFiles[i] };

// Add all tasks to the job
batchClient.JobOperations.AddTask(JobId, tasks);

// Wait for tasks to complete (timeout after 30 mins)
batchClient.Utilities.CreateTaskStateMonitor().WaitAll(addedTasks, TaskState.Completed, TimeSpan.FromMinutes(30));

// Task standard output file
task.GetNodeFile(Constants.StandardOutFileName).ReadAsString();

csharp 在Startup.cs上设置招摇

Startup_services.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new Info
        {
            Version = "v1",
            Title = "Title",
            Description = "Description",
            TermsOfService = "For internal use only",
            Contact = new Contact
            {
                Name = "me",
                Email = "me@domain.com",
                Url = "domain.com"
            },
            License = new License
            {
                Name = "Internal use only",
                Url = "domain.com"
            }
        });

        c.EnableAnnotations();
    });
}
Startup_configure.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseMvc();
    app.UseSwagger();

    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "Trace Past Due API V1");
        c.RoutePrefix = string.Empty;
    });
}

csharp 在Program.cs中设置appsettings

Program.cs
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
    {
        var webHostBuilder = WebHost.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((builderContext, config) =>
            {
                config.AddJsonFile($"appsettings.{Environment.MachineName}.json", optional: true,
                    reloadOnChange: true);
            })
            .UseStartup<Startup>();

        if (args.Length == 1 && long.TryParse(args[0], out var portNumber))
            webHostBuilder = webHostBuilder.UseUrls($"http://localhost:{portNumber}/");

        return webHostBuilder;
    }