Skip to content

Instantly share code, notes, and snippets.

@JaimeStill
Last active July 13, 2017 20:06
Show Gist options
  • Save JaimeStill/159895a69ae103bdce744955c00be7ad to your computer and use it in GitHub Desktop.
Save JaimeStill/159895a69ae103bdce744955c00be7ad to your computer and use it in GitHub Desktop.
Snippet notes related to .NET technologies

.NET

Contents

back to top

Expression Bodied Properties

public class Demo
{
    public string Name { get; set; }
    public string FirstName => Name.Split(' ')[0];
    public string LastName => Name.Split(' ')[1];
    public bool HasName => !string.IsNullOrEmpty(Name);
}

DateTimeOffset-based Expression Bodied Property

public class Event
{
    public DateTimeOffset EventDate { get; set; }
    public bool IsInFuture => EventDate > DateTimeOffset.Now;
    public bool IsNew => !IsInFuture && (DateTimeOffset.Now - EventDate).TotalDays <= 7;
}

Debug C# .NET Core Apps in Visual Studio Code

project.json

"buildOptions": {
  "debugType": "portable"
}

Deserialize JSON

public static Task<T> DeserializeJson<T>(this string json)
{
    return Task.Run(() =>
    {
        return JsonConvert.DeserializeObject<T>(json);
    });
}

Entity model = await provider.FormData["model"].DeserializeJson<Entity>();
}

Even though this extension method emulates the behavior of JsonConvert.DeserializeObject<T>, it is beneficial, because it decouples the application from Newtonsoft.Json. If the implementation from Newtonsoft.Json changes in a way that would affect the application, I only need to modify this extension method.

Execute .PS1 Script From C# With Provided Parameters

Program.cs

using PowerShellRef.Core;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace PowerShellRef.Testing
{
    class Program
    {
        static void Main(string[] args)
        {
            CancellationTokenSource cts = new CancellationTokenSource();

            Console.CancelKeyPress += (s, e) =>
            {
                e.Cancel = true;
                cts.Cancel();
            };

            MainAsync(args, cts.Token).Wait();
        }

        static async Task MainAsync(string[] args, CancellationToken token)
        {
            await WmiQueryExtensions.TestWmiQueries();
        }
    }
}

QueryWmi.ps1

[CmdletBinding()]
Param(
  [Parameter()]
  [string]$query,
  [Parameter()]
  [string]$filename,
  [Parameter()]
  [string]$properties,
  [Parameter()]
  [string]$computername,
  [Parameter()]
  [string]$wmiNamespace
)
$wmi = Get-WmiObject -ComputerName $computername -Namespace $wmiNamespace -Query $query
$wmi | select $properties | Export-Csv ${ENV:USERPROFILE}\Desktop\$filename.csv

ServiceNames.txt

select * from Win32_Service

WmiQueryExtensions.cs

using System;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Text;
using System.Threading.Tasks;

namespace PowerShellRef.Core
{
    public static class WmiQueryExtensions
    {
        public static Task TestWmiQueries()
        {
            return Task.Run(() =>
            {
                string query = System.IO.File.ReadAllText(@"ServiceNames.txt");
                string filename = "CLR_PS_SCRIPT_TEST";
                string[] properties = new string[]
                {
                    "Name",
                    "PathName",
                    "DisplayName"
                };

                string computername = "MonsterRig";
                string wmiNamespace = @"root\cimv2";
                string scriptUrl = @"QueryWmi.ps1";

                InitialSessionState iss = InitialSessionState.CreateDefault();
                iss.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Unrestricted;

                using (Runspace rs = RunspaceFactory.CreateRunspace(iss))
                {
                    rs.Open();

                    Command queryWmi = new Command(scriptUrl);
                    queryWmi.Parameters.Add("query", query);
                    queryWmi.Parameters.Add("filename", filename);
                    queryWmi.Parameters.Add("properties", properties);
                    queryWmi.Parameters.Add("computername", computername);
                    queryWmi.Parameters.Add("wmiNamespace", wmiNamespace);

                    using (PowerShell ps = PowerShell.Create())
                    {
                        ps.Runspace = rs;
                        ps.Commands.AddCommand(queryWmi);
                        ps.Invoke();

                        if (ps.HadErrors)
                        {
                            if (ps.Streams.Error.Count > 0)
                            {
                                foreach (var error in ps.Streams.Error)
                                {
                                    Console.WriteLine(error.Exception.GetExceptionMessageChain());
                                }
                            }
                            else
                            {
                                Console.WriteLine("Unspecified Script Execution Error");
                            }
                        }
                        else
                        {
                            Console.WriteLine(scriptUrl + " executed successfully");
                        }
                    }

                    rs.Close();
                }

                Console.ReadLine();
            });
        }

        public static string GetExceptionMessageChain(this Exception ex)
        {
            var message = new StringBuilder(ex.Message);
            message.AppendLine();

            if (ex.InnerException != null)
            {
                message.AppendLine(GetExceptionMessageChain(ex.InnerException));
            }

            return message.ToString();
        }
    }
}

back to top

Restore EF Tools to Package Manager Console

Verify the version of EF you're using, and update the below accordingly

Import-Module .\packages\EntityFramework.6.1.3\tools\EntityFramework.psm1

Reusable Entity Projection Queries

public static Task<IEnumerable<DataModel>> GetSomeDataCollection(this AppDbContext context, int userId)
{
  return Task.Run(() =>
  {
    var model = context.Data.Where(x => x.AppUserId == userId).GetData();
  });
}

public static Task<IEnumerable<DataModel>> GetPendingDataCollection(this AppDbContext context, int userId)
{
  return Task.Run(() =>
  {
    var model = context.Data.Where(x => x.Verifications.Count < 1).GetData();
  });
}

// If the signature of the entity to model projection ever changes, it only needs to be
// updated here. Can focus above queries on any necessary filtering that makes them unique
// without worrying about the details of projecting the data into a view model
public static IEnumerable<DataModel> GetData(this IQueryable<Datum> data)
{
  return data.Select(x => new DataModel
  {
    id = x.Id,
    title = x.Title,
    description = x.Description,
    appUser = new AppUserModel
    {
      id = x.AppUserId,
      displayName = x.AppUser.DisplayName
    },
    dateCreated = x.DateCreated
  }).OrderBy(x => x.dateCreated).AsEnumerable();
}

Cast To ViewModel Extension Method

Re-usable cast method for projecting a Data entity to a DataModel entity. This method can be used for retrieving a single instance or multiple instances from a DbContext.

public static DataModel CastToDataModel(this Data data)
{
    var model = new DataModel
    {
        id = x.Id,
        title = x.Title,
        description = x.Description,
        appUser = new AppUserModel
        {
            id = x.AppUserId,
            displayName = x.AppUser.DisplayName
        },
        dateCreated = x.DateCreated
    };
    
    return model;
}

public static Task<IEnumerable<DataModel>> GetData(this AppDbContext db)
{
    var model = db.Data.Select(x => x.CastToDataModel());
    return model;
}

public static async Task<DataModel> GetDatum(this AppDbContext db, int id)
{
    var datum = await db.Data.FirstOrDefaultAsync(x => x.Id == id);
    return datum.CastToDataModel();
}

Mapping Same Entity with Multiple Foreign Keys

Fluent API Mapping of one entity that contains multiple foreign key relationships in another single entity

Person.cs

public class Person
{
  public int Id { get; set; }
  public string Name { get; set; }
  
  public virtual ICollection<Order> SentOrders { get; set; }
  public virtual ICollection<Order> ReceivedOrders { get; set; }
}

Order.cs

public class Order
{
  public int Id { get; set; }
  public int SenderId { get; set }
  public int RecipientId { get; set; }
  
  public Person Sender { get; set; }
  public Person Recipient { get; set; }
}

AppDbContext.cs

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
  base.OnModelCreating(modelBuilder);
  
  modelBuilder.Entity<Order>()
    .HasRequired(x => x.Sender)
    .WithMany(x => x.SentOrders)
    .HasForeignKey(x => x.SenderId)
    .WillCascadeOnDelete(false);
    
  modelBuilder.Entity<Order>()
    .HasRequired(x => x.Recipient)
    .WithMany(x => x.ReceivedOrders)
    .HasForeignKey(x => x.RecipientId)
    .WillCascadeOnDelete(false);
}

back to top

Web API File Select

This is relative to ASP.NET MVC 5 and Web API 2

See Angular fileSelect Directive

UploadExtensions.cs

public static class UploadExtensions
{
  public static async Task AddFiles(this AppDbContext context, Collection<MultipartFileData> files, string uploadUrl)
  {
    if (files.Count > 0)
    {
      foreach (var file in files)
      {
        // See: https://github.com/JaimeStill/Reference/wiki/ASP.NET-WebAPI-File-Upload
        var fileName = await file.LocalFileName.GetCleanFileName();
        
        // Demo of what how to persist in database
        Attachment attachment = new Attachment
        {
          Name = fileName,
          Url = uploadUrl + fileName,
          UploadDate = DateTime.Now
        };
        
        context.Attachments.Add(attachment);
        await context.SaveChangesAsync();
      }
    }
  }
}

UploadApiController.cs

public class UploadApiController : ApiController
{
  private AppDbContext context;
  
  public AppDbContext Context
  {
    get
    {
      return context ?? Request.GetOwinContext().Get<AppDbContext>();
    }
    private set
    {
      context = value;
    }
  }
  
  private const string UPLOAD_URL = @"\\..."; // whatever URL you want to save files to
  
  [Route("api/demo/addFiles")]
  [HttpPut]
  public async Task AddFiles()
  {
    // See: https://github.com/JaimeStill/Reference/wiki/ASP.NET-WebAPI-File-Upload
    FileNameMultipartFormDataStreamProvider provider = await Request.Content.GetMultipartFormData(UPLOAD_URL);
    await Context.AddFiles(provider.FileData);
  }
}

mimeMap Configuration in Web.config

<configuration>
  <system.webServer>
    <staticContent>
      <mimeMap mimeType="text/plain" fileExtensions=".log" />
    </staticContent>
  </system.webServer>
</configuration>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment