Extremely useful compatibility list, especially for debugging purposes:
Author: Matt
Microsoft REST API Guideline
Excellent reading from Microsoft: https://github.com/Microsoft/api-guidelines/blob/vNext/Guidelines.md
PowerShell Cheatsheet
Operation | cmd | PowerShell |
Get a simple directory listing |
dir |
get-childitem alias: dir |
Get a recursive directory listing |
dir /s |
get-childitem -recurse alias: dir -r |
Get a wide directory list |
dir /w |
dir | format-wide alias: dir | fw |
List built-in commands |
help |
get-command alias: help |
Copy a file |
copy foo.txt bar.txt |
copy-item foo.txt bar.txt alias: copy foo.txt bar.txt |
Move a file |
move foo.txt c:\ |
move-item foo.txt d:\ alias: move foo.txt d:\ |
Rename a file |
ren foo.txt bar.txt |
rename-item foo.txt bar.txt alias: ren foo.txt bar.txt |
Batch rename |
ren *.one *.two |
dir *.pdf | rename -newname {$_.name -rep ".one",".two"} |
Set the current directory to d:\ |
d: cd \ |
set-location d:\ alias: cd d:\ |
Clear the screen |
cls |
clear-host alias: cls |
List only directories |
dir /ad |
dir | where { $_.MshIsContainer } |
Directory list, sorted by date |
dir /od |
dir | sort-object LastWriteTime |
Directory list, sorted by date, descending order |
dir /o-d |
dir | sort-object LastWriteTime -desc |
Show the current directory |
cd |
get-location alias: pwd |
See a command’s help |
dir /? |
get-help get-command or: get-help get-command -detailed or: get-help get-command -full or: dir -? |
List environment variables |
set |
dir env: |
Delete a file |
del foo.txt |
remove-item foo.txt alias: del foo.txt |
Find all *.txt files |
dir /s *.txt |
get-childitem -recurse -include *.txt alias: dir -r -i *.txt |
Find all *.txt files containing a particular string |
findstr "foo" *.txt |
dir *.txt | select-string "foo" |
Show a list of services |
net start |
get-service |
Start a service |
net start MyService |
start-service MyService |
Stop a service |
net stop MyService |
stop-service MyService |
Show network shares |
net share |
gwmi Win32_Share |
Show a list of running processes |
tasklist |
get-process alias: ps |
Kill all notepad.exe processes |
taskkill /im notepad.exe /f |
ps notepad | kill |
Useful patterns for DateTime.ToString()
Custom DateTime.ToString() formats
d | day of the month as a number from 1 through 31 – a single-digit day is formatted without a leading zero |
dd | day of the month as a number from 01 through 31 – a single-digit day is formatted with a leading zero |
ddd | abbreviated name of the day of the week (Mon, Tues, Wed etc) |
dddd | full name of the day of the week (Monday, Tuesday etc) |
h | 12-hour clock hour (e.g. 7) |
hh | 12-hour clock, with a leading 0 (e.g. 07) |
H | 24-hour clock hour (e.g. 19) |
HH | 24-hour clock hour, with a leading 0 (e.g. 19) |
m | minutes |
mm | minutes with a leading zero |
M | month number |
MM | month number with leading zero |
MMM | abbreviated Month Name (e.g. Dec) |
MMMM | full month name (e.g. December) |
s | seconds |
ss | seconds with leading zero |
t | abbreviated AM / PM (e.g. A or P) |
tt | AM / PM (e.g. AM or PM |
y | year, no leading zero (e.g. 2001 would be 1) |
yy | year, leadin zero (e.g. 2001 would be 01) |
yyy | year, (e.g. 2001 would be 2001) |
yyyy | year, (e.g. 2001 would be 2001) |
K | time zone information of a date and time value (e.g. +05:00) |
z | with DateTime values, represents the signed offset of the local operating system’s time zone from Coordinated Universal Time (UTC), measured in hours. (e.g. +6) |
zz | as z but with leadin zero (e.g. +06) |
zzz | with DateTime values, represents the signed offset of the local operating system’s time zone from UTC, measured in hours and minutes. (e.g. +06:00) |
f | most significant digit of the seconds fraction; that is, it represents the tenths of a second in a date and time value. |
ff | two most significant digits of the seconds fraction; that is, it represents the hundredths of a second in a date and time value |
fff | three most significant digits of the seconds fraction; that is, it represents the milliseconds in a date and time value |
ffff | four most significant digits of the seconds fraction; that is, it represents the ten thousandths of a second in a date and time value |
fffff | five most significant digits of the seconds fraction; that is, it represents the hundred thousandths of a second in a date and time value |
ffffff | six most significant digits of the seconds fraction; that is, it represents the millionths of a second in a date and time value |
the seven most significant digits of the seconds fraction; that is, it represents the ten millionths of a second in a date and time value | |
F | most significant digit of the seconds fraction; that is, it represents the tenths of a second in a date and time value. Nothing is displayed if the digit is zero. |
: | the time separator defined in the current DateTimeFormatInfo..::.TimeSeparator property. This separator is used to differentiate hours, minutes, and seconds. |
/ | date separator defined in the current DateTimeFormatInfo..::.DateSeparator property. This separator is used to differentiate years, months, and days. |
“ | quoted string (quotation mark). Displays the literal value of any string between two quotation marks (“). Your application should precede each quotation mark with an escape character (\). |
‘ | quoted string (apostrophe). Displays the literal value of any string between two apostrophe (‘) characters. |
%c | the result associated with a c custom format specifier, when the custom date and time format string consists solely of that custom format specifier. That is, to use the d, f, F, h, m, s, t, y, z, H, or M custom format specifier by itself, the application should specify %d, %f, %F, %h, %m, %s, %t, %y, %z, %H, or %M. For more information about using a single format specifier, see Using Single Custom Format Specifiers. |
The patterns for DateTime.ToString ( ‘d’ ) :
0 | MM/dd/yyyy | 08/22/2006 |
The patterns for DateTime.ToString ( ‘D’ ) :
0 | dddd, dd MMMM yyyy | Tuesday, 22 August 2006 |
The patterns for DateTime.ToString ( ‘f’ ) :
0 | dddd, dd MMMM yyyy HH:mm | Tuesday, 22 August 2006 06:30 |
1 | dddd, dd MMMM yyyy hh:mm | tt Tuesday, 22 August 2006 06:30 AM |
2 | dddd, dd MMMM yyyy H:mm | Tuesday, 22 August 2006 6:30 |
3 | dddd, dd MMMM yyyy h:mm | tt Tuesday, 22 August 2006 6:30 AM |
The patterns for DateTime.ToString ( ‘F’ ) :
0 | dddd, dd MMMM yyyy HH:mm:ss | Tuesday, 22 August 2006 06:30:07 |
The patterns for DateTime.ToString ( ‘g’ ) :
0 | MM/dd/yyyy HH:mm | 08/22/2006 06:30 |
1 | MM/dd/yyyy hh:mm | tt 08/22/2006 06:30 AM |
2 | MM/dd/yyyy H:mm | 08/22/2006 6:30 |
3 | MM/dd/yyyy h:mm tt | 08/22/2006 6:30 AM |
The patterns for DateTime.ToString ( ‘G’ ) :
0 | MM/dd/yyyy HH:mm:ss | 08/22/2006 06:30:07 |
The patterns for DateTime.ToString ( ‘m’ ) :
0 | MMMM dd | August 22 |
The patterns for DateTime.ToString ( ‘r’ ) :
0 | ddd, dd MMM yyyy HH’:’mm’:’ss ‘GMT’ | Tue, 22 Aug 2006 06:30:07 GMT |
The patterns for DateTime.ToString ( ‘s’ ) :
0 | yyyy’-‘MM’-‘dd’T’HH’:’mm’:’ss | 2006-08-22T06:30:07 |
The patterns for DateTime.ToString ( ‘u’ ) :
0 | yyyy’-‘MM’-‘dd HH’:’mm’:’ss’Z’ | 2006-08-22 06:30:07Z |
The patterns for DateTime.ToString ( ‘U’ ) :
0 | dddd, dd MMMM yyyy HH:mm:ss | Tuesday, 22 August 2006 06:30:07 |
The patterns for DateTime.ToString ( ‘y’ ) :
0 | yyyy MMMM 2006 August |
AutoFixture customization for ASP.Net Core Web API controller
Lets start with simple controller:
[Route("api/[controller]") public class TestController : Controller { [HttpGet("")] public IActionResult Get() { return Ok(); } }
Now we want to create unit test for this method using AutoFixture/Moq/Shouldly/XUnit stack:
public class TestControllerTests { [Theory, AutoMoqData] public void Get_ShouldReturn_HttpStatusOk(TestController sut) { // act.. var actual = sut.Get(); // assert.. actual.ShouldNotBeNull(); actual.ShouldBeOfType() } }
Test runner will crash saying:
AutoFixture.ObjectCreationException : AutoFixture was unable to create an instance from Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary because creation unexpectedly failed with exception. Please refer to the inner exception to investigate the root cause of the failure. Request path: J2BI.Holidays.TravelDocs.Api.Controllers.AccommodationController sut --> J2BI.Holidays.TravelDocs.Api.Controllers.AccommodationController --> Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData --> Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ---- System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation. -------- Castle.DynamicProxy.InvalidProxyConstructorArgumentsException : Can not instantiate proxy of class: Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata. Could not find a parameterless constructor.
The problem lies in lack of parameterless constructor for ModelMetadata class.
This can easily be fixed with AutoFixture customization:
public class ApiControllerCustomization : ICustomization { public void Customize(IFixture fixture) { fixture.Register(() => new CustomCompositeMetadataDetailsProvider()); fixture.Inject(new ViewDataDictionary(fixture.Create(), fixture.Create())); } private class CustomCompositeMetadataDetailsProvider : ICompositeMetadataDetailsProvider { public void CreateBindingMetadata(BindingMetadataProviderContext context) { throw new System.NotImplementedException(); } public void CreateDisplayMetadata(DisplayMetadataProviderContext context) { throw new System.NotImplementedException(); } public void CreateValidationMetadata(ValidationMetadataProviderContext context) { throw new System.NotImplementedException(); } } }
This now has to be wrapped in data attribute:
public class AutoApiMoqDataAttribute : AutoDataAttribute { public AutoApiMoqDataAttribute() : base(() => { var fixture = new Fixture(); fixture.Customize(new ApiControllerCustomization()) .Customize(new AutoMoqCustomization()) .Behaviors.Add(new OmitOnRecursionBehavior()); return fixture; }) { } }
Voila! Now the test will pass.
Check out this gist
Best Practices for RESTful API
1. Use nouns but no verbs
For an easy understanding use this structure for every resource:
Resource | GET read |
POST create |
PUT update |
DELETE |
/cars | Returns a list of cars | Create a new car | Bulk update of cars | Delete all cars |
/cars/711 | Returns a specific car | Method not allowed (405) | Updates a specific car | Deletes a specific car |
2. GET method and query parameters should not alter the state
Use PUT, POST and DELETE methods instead of the GET method to alter the state.
3. Use plural nouns
Keep it simple and use only plural nouns for all resources.
/users instead of /user
4. Use sub-resources for relations
If a resource is related to another resource use subresources.
GET /cars/711/drivers/ Returns a list of drivers for car 711
5. Use HTTP headers for serialization formats
Both, client and server, need to know which format is used for the communication. The format has to be specified in the HTTP-Header.
Content-Type defines the request format.
Accept defines a list of acceptable response formats.
6. Handle Errors with HTTP status codes
It is hard to work with an API that ignores error handling. Pure returning of a HTTP 500 with a stacktrace is not very helpful.
Use HTTP status codes
The HTTP standard provides over 70 status codes to describe the return values. We don’t need them all, but there should be used at least a mount of 10.
200 – OK – Eyerything is working
201 – OK – New resource has been created
204 – OK – The resource was successfully deleted
304 – Not Modified – The client can use cached data
400 – Bad Request – The request was invalid or cannot be served. The exact error should be explained in the error payload. E.g. „The JSON is not valid“
401 – Unauthorized – The request requires an user authentication
403 – Forbidden – The server understood the request, but is refusing it or the access is not allowed.
404 – Not found – There is no resource behind the URI.
422 – Unprocessable Entity – Should be used if the server cannot process the enitity, e.g. if an image cannot be formatted or mandatory fields are missing in the payload.
500 – Internal Server Error – API developers should avoid this error. If an error occurs in the global catch blog, the stracktrace should be logged and not returned as response.
7. Provide filtering, sorting, field selection and paging for collections
Filtering:
Use a unique query parameter for all fields or a query language for filtering.
GET /cars?color=red Returns a list of red cars GET /cars?seats<=2 Returns a list of cars with a maximum of 2 seats
Sorting:
Allow ascending and descending sorting over multiple fields.
GET /cars?sort=-manufactorer,+model
This returns a list of cars sorted by descending manufacturers and ascending models.
Field selection
Mobile clients display just a few attributes in a list. They don’t need all attributes of a resource. Give the API consumer the ability to choose returned fields. This will also reduce the network traffic and speed up the usage of the API.
GET /cars?fields=manufacturer,model,id,color
Paging
Use limit and offset. It is flexible for the user and common in leading databases. The default should be limit=20 and offset=0
GET /cars?offset=10&limit=5
To send the total entries back to the user use the custom HTTP header: X-Total-Count.
Three simple steps to enable Swagger on ASP.NET Core WebAPI
Step 1. Install NuGet package:
Install-Package Swashbuckle.AspNetCore
Step 2. Navigate to Startup.cs and add following code inside ConfigureServices() method
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });
});
Step 3. Add following code inside Configure() method
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
);
Voila!
MS SQL Server object types
List of MS SQL Server object types:
- C – CHECK_CONSTRAINT
- D – DEFAULT_CONSTRAINT
- F – FOREIGN_KEY_CONSTRAINT
- FN- SQL_SCALAR_FUNCTION
- IF – SQL_INLINE_TABLE_VALUED_FUNCTION
- IT – INTERNAL_TABLE
- P – SQL_STORED_PROCEDURE
- PK – PRIMARY_KEY_CONSTRAINT
- S – SYSTEM_TABLE
- SQ – SERVICE_QUEUE
- TR – SQL_TRIGGER
- U – USER_TABLE
- UQ – UNIQUE_CONSTRAINT
- V – VIEW
This can be obtained with simple query:
select distinct type, type_desc from sys.objects order by 1
Automatic generation of EF entities and mappings from existing database schema
This is a bunch of useful scripts for generating C# Entity Framework Code First POCOs from existing database schema.
First, let’s create T-SQL function for generating C# class for EF entity:
This function deliberately ignores certain columns, (Created On/By, Modified On/By). This properties are pushed to EntityBase class, which our POCO inherits from. All other columns in DB table will be mapped to corresponding C# type.
Next, let’s create T-SQL function for EF configuration (mapping class):
Now, let’s put it all together in one script:
All source code is available here
Git aliases I can’t live without
Being still quite new to git (and moving from world of VSS/TFS), I became big fan of Git’s flexibility and configuration. It really boosts productivity and makes developer’s life much easier.
Below I list git aliases I found most useful. For sure this list will grow in future. They need to be added to .gitconfig file in [alias] section:
[alias]
cam = commit -am
st = status
aa = add .
ba = branch -a
co = checkout
hist = log --oneline -10
Alternatively, they can be enabled via git command:
git config --global alias.st status