This blog now forces HTTPS connections
After a month of trial with no one to complain of HTTPS issues, I've decided to set the blog to redirect normal connections to the secure URL. Let me know if you experience any problems.
After a month of trial with no one to complain of HTTPS issues, I've decided to set the blog to redirect normal connections to the secure URL. Let me know if you experience any problems.
In September last year I was leaving my job and starting a sabbatical year, with many plans for what seemed then like a lot of time in which to do everything. I was severely underestimating my ability to waste time. Now the year is almost over and I need to start thinking about the technologies in my field of choice that I need to catch up with; and, boy, there is a lot of them! I leave the IT industry alone for one year and kaboom! it blows up like an angry volcano. To be honest, not all of these things that are new for me are just one year old, some I was just ignoring as I didn't need them for my various jobs. Learn from this, as especially in the software business it gets harder and harder to keep up to date and easier and easier to live in a bubble of your own or your employer's creation.
A friend of mine has been employed to write code in the new Microsoft cross-platform ASP.Net Mvc Core and one day he asked be about the difference between the [Required] and the [BindRequired] attributes. Not being an expert in ASP.Net MVC and even less in the Core version, I had no idea so I went exploring.public IActionResult Test([FromBody]TestModel model)TestModel is a simple POCO with Required and BindRequired attributes set on its properties: public class TestModelNow, if I send an object like this
{
[Required]
public string A { get; set; }
[BindRequired]
public string B { get; set; }
}
{ A:'Something',B:'Something else' }I get a true ModelState.IsValid value. If I send only property A, I also get a valid model. If I send only B or an empty object, IsValid will be false. So [Required] works as expected, [BindRequired] doesn't seem to do anything.var valid = TryUpdateModelAsync(model).Result;, valid will be true. However, if you fail to specify a B parameter, valid will be false. Note that the properties of the model change either way. Property A will be filled with whatever you send it, only the result of the attempt will be false.public IActionResult Test(TestModel model)and now the request /api/test/test&A=Something&B=SomethingElse fills the object without the need for content (and ignoring it if it exists). If I remove either A or B, ModelState.IsValid becomes false.
Democracy, like any other system of government or political system, is designed to keep the powerful in the driver's seat. It's not about the good of the people, unless they hold power. It was invented and implemented at times when having a large group of people supporting you meant something, gave you the ability to do things. Any other system: theocracy, tyranny, feudalism, communism, fascism... they all do the same thing and fail when the group they support fails to maintain power. Democracy is not about the little people, it's about how fast a system can adapt to changes in the structures of power. It is just the "agile" version of the same old thing. By declaring its ruling group "the people", democracy can survive any political change. The system outlives groups and groups of "people".
Another entry from my ".NET with Visual Studio Code" series, this will discuss the default web site generated by the 'dotnet new' command. I recommend reading the previous articles:"launchBrowser" : {
"enabled" : true,
"args" : "${auto-detect-url}",
"windows" : {
"command" : "cmd.exe",
"args" : "/C start ${auto-detect-url}"
},
"osx" : {
"command" : "open"
},
"linux" : {
"command" : "xdg-open"
}
}
{
"name": "webapplication",
"private": true,
"dependencies": {
"bootstrap": "3.3.6",
"jquery": "2.2.3",
"jquery-validation": "1.15.0",
"jquery-validation-unobtrusive": "3.2.6"
}
}and there is also a .bowerrc file indicating the destination folder:{
"directory": "wwwroot/lib"
}. This probably has to do with that Gulp and Bower line in the Readme file.npm install -g bower. Oh, you gotta love the ASCII colors and the loader! Soooo cuuuute!
npm install --global gulpHere tutorials say to install it in your project's folder again:
npm install --save-dev gulpWhy do we need to install gulp twice, once globally and once locally? Because reasons. However, I noticed that in the project there is already a package.json containing what I need for the project:
{
"name": "webapplication",
"version": "0.0.0",
"private": true,
"devDependencies": {
"gulp": "3.9.1",
"gulp-concat": "2.6.0",
"gulp-cssmin": "0.1.7",
"gulp-uglify": "1.5.3",
"rimraf": "2.5.2"
}
}Gulp is among them so I just run npm install --save-devwithout specifying a package and it installs what I need. The install immediately gave me some concerning warnings like "graceful-fs v3.0.0 will fail on node releases >=7.0. Please update to graceful-fs 4.0.0" and "please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue" and "lodash v3.0.0 is no longer maintained. Upgrade to lodash v4.0.0". Luckily, the error messages are soon replaced by a random ASCII tree and if you can't scroll up you're screwed :) One solution is to pipe the output to a file or to NUL so that the ASCII tree of the packages doesn't scroll the warnings up
npm install --save-dev >nul
"scripts": {There is npm install, there is bower install and the two tasks for gulp: clean and min.
"prepublish": [ "npm install", "bower install", "gulp clean", "gulp min" ],
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
}
public IConfigurationRoot Configuration { get; }Here is the appsettings.json file that is being loaded there:
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
Configuration = builder.Build();
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=WebApplication.db"
},
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}Later on these configuration settings will be used in code:services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(Configuration.GetConnectionString("DefaultConnection"))
);
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
builder.AddUserSecrets();
builder.AddEnvironmentVariables();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(Configuration.GetConnectionString("DefaultConnection"))
);
"Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore": "1.0.0",Let's go with it for now, though.
"Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0",
"Microsoft.EntityFrameworkCore.Sqlite": "1.0.0",
"Microsoft.EntityFrameworkCore.Tools": {
"version": "1.0.0-preview2-final",
"type": "build"
}
SqliteException: SQLite Error 1: 'no such table: AspNetUsers'.
There are migrations for ApplicationDbContext that have not been applied to the database
In Visual Studio, you can use the Package Manager Console to apply pending migrations to the database:
PM> Update-Database
Alternatively, you can apply pending migrations from a command prompt at your project directory:
> dotnet ef database update
dotnet ef database update(make sure you stop the running web server before you run the command)? It compiles the project and it completes in a few seconds. Let's run the app again and attempt to register. It works!
if (env.IsDevelopment())which installs the MigrationsEndPointMiddleware. Documentation for it here.
{
...
app.UseDatabaseErrorPage();
...
}
dotnet runin your project folder. You can just as well use
dotnet compiled.dll, but you need to also run it from the project root. In the former case, dotnet will also compile the project for you, in the latter it will just run whatever is already compiled.
This is part of the .NET Core and VS Code series, which contains:,"Microsoft.AspNetCore.Mvc": "1.0.0"
,"Microsoft.AspNetCore.Mvc.Core": "1.0.0"
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.1" />to ItemGroup in API.csproj and tell the project to use MVC in code. This is done by adding services.AddMvc(); in ConfigureServices and replacing the app.Run line in Configure with app.UseMvcWithDefaultRoute(); in Program.cs.
{
"version": "1.0.0-*",
"buildOptions": {
"debugType": "portable",
"emitEntryPoint": true
},
"dependencies": {},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
},
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
"Microsoft.AspNetCore.Mvc": "1.0.0",
"Microsoft.AspNetCore.Mvc.Core": "1.0.0"
},
"imports": "dnxcore50"
}
}
}<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Folder Include="wwwroot\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.1" />
</ItemGroup>
</Project>
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
namespace WebCore.API
{
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace WebCore.API
{
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvcWithDefaultRoute();
/*app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});*/
}
}
}
{
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (web API)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceRoot}/bin/Debug/netcoreapp1.0/API.dll",
"args": [],
"cwd": "${workspaceRoot}",
"externalConsole": false,
"stopAtEntry": false
}
]
}using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
namespace WebCore.API.Controllers
{
[Route("api/[controller]")]
public class NoteController : Controller
{
private static List<Note> _notes;
static NoteController()
{
_notes = new List<Note>();
}
[HttpGet]
public IEnumerable<Note> GetAll()
{
return _notes.AsReadOnly();
}
[HttpGet("{id}", Name = "GetNote")]
public IActionResult GetById(string id)
{
var item = _notes.Find(n => n.Id == id);
if (item == null)
{
return NotFound();
}
return new ObjectResult(item);
}
[HttpPost]
public IActionResult Create([FromBody] Note item)
{
if (item == null)
{
return BadRequest();
}
item.Id = (_notes.Count + 1).ToString();
_notes.Add(item);
return CreatedAtRoute("GetNote", new { controller = "Note", id = item.Id }, item);
}
[HttpDelete("{id}")]
public void Delete(string id)
{
_notes.RemoveAll(n => n.Id == id);
}
public class Note
{
public string Id { get; set; }
public string Content { get; set; }
}
}
}
{
Content:'test'
}:{
"id": "1",
"content": "test"
}app.UseMvcWithDefaultRoute();is the code that enables that behavior. Let me demonstrate more of this "magic". In our example so far I've hardcoded the Note class inside the Controller class, but usually the class would be part of the functionality of the API and there would be a repository handling saving stuff in the database.
services.AddSingletonwe tell Core that for a request of the implementation for INoteRepository, return the singleton instance of NoteRepository. From this line alone Core knows to initialize the NoteController constructor with the correct repository instance.();
I started reading the book knowing nothing of its author or contents or, indeed, the publishing date. For me it felt like a philosophical treatise on revolutions in general, especially since the names of the countries were often omitted and it seemed that the author was purposeful in trying to make it apply to any era and any nation. Only after finishing the book I realized that Darkness at Noon was a story published in 1940, by Arthur Koestler, a Hungarian-British author who was briefly part of the German Communist movement before he left it, disillusioned. The main character is probably a more dramatic version of himself. As an aside and a fun coincidence, in July 2015 the original German manuscript of the book was found. All the since published versions are based on an English translation after Koestler lost the original. Even the published German version is a retranslation from English by Koestler himself.
This is part of the .NET Core and VS Code series, which contains:,"Microsoft.AspNetCore.Server.Kestrel": "1.0.0"to dependencies (right after Microsoft.NETCore.App)
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" />
</ItemGroup>
using Microsoft.AspNetCore.Hosting;and replacing the Console.WriteLine thing with
var host = new WebHostBuilder()
.UseKestrel()
.UseStartup<Startup>()
.Build();
host.Run();
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
namespace <your namespace here>
{
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Run(context =>
{
return context.Response.WriteAsync("Hello from ASP.NET Core!");
});
}
}
}
"Microsoft.Extensions.Logging": "1.0.0", which needs to be added to dependencies in project.json.
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Logging;
namespace ConsoleApplication
{
public class Startup
{
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
var logger=loggerFactory.CreateLogger("Sample app logger");
logger.LogInformation("Starting app");
}
}
}
{
"version": "1.0.0-*",
"buildOptions": {
"debugType": "portable",
"emitEntryPoint": true
},
"dependencies": {},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
},
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
"Microsoft.Extensions.Logging": "1.0.0"
},
"imports": "dnxcore50"
}
}
}
"Microsoft.Extensions.Logging.Console": "1.0.0"to project.json. What AddConsole does is actually factory.AddProvider(new ConsoleLoggerProvider(...));. The provider will then instantiate a ConsoleLogger for the logger chain, which will write to the console.
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.1" />package, we instruct the WebHostBuilder what the web root is, then we tell the ApplicationBuilder to use static files. Like this:
{
"version": "1.0.0-*",
"buildOptions": {
"debugType": "portable",
"emitEntryPoint": true
},
"dependencies": {},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
},
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
"Microsoft.AspNetCore.StaticFiles": "1.0.0"
},
"imports": "dnxcore50"
}
}
}<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.1" />
</ItemGroup>
</Project>
using System.IO;
using Microsoft.AspNetCore.Hosting;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
var path=Path.Combine(Directory.GetCurrentDirectory(),"www");
var host = new WebHostBuilder()
.UseKestrel()
.UseWebRoot(path)
.UseStartup<Startup>()
.Build();
host.Run();
}
}
}
using Microsoft.AspNetCore.Builder;
namespace ConsoleApplication
{
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.UseStaticFiles();
}
}
}
"Microsoft.AspNetCore.Routing": "1.0.0"to project.json, then add some silly routing to Startup.cs:
{
"version": "1.0.0-*",
"buildOptions": {
"debugType": "portable",
"emitEntryPoint": true
},
"dependencies": {},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
},
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
"Microsoft.AspNetCore.Routing": "1.0.0"
},
"imports": "dnxcore50"
}
}
}using Microsoft.AspNetCore.Hosting;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseStartup<Startup>()
.Build();
host.Run();
}
}
}
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
namespace ConsoleApplication
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddRouting();
}
public void Configure(IApplicationBuilder app)
{
app.UseRouter(new HelloRouter());
}
public class HelloRouter : IRouter
{
public VirtualPathData GetVirtualPath(VirtualPathContext context)
{
return null;
}
public Task RouteAsync(RouteContext context)
{
var requestPath = context.HttpContext.Request.Path;
if (requestPath.StartsWithSegments("/hello", StringComparison.OrdinalIgnoreCase))
{
context.Handler = async c =>
{
await c.Response.WriteAsync($"Hello world!");
};
}
return Task.FromResult(0);
}
}
}
}
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
namespace ConsoleApplication
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddRouting();
}
public void Configure(IApplicationBuilder app)
{
var defaultHandler = new RouteHandler(
c => c.Response.WriteAsync($"Default handler! Route values: {string.Join(", ", c.GetRouteData().Values)}")
);
var routeBuilder = new RouteBuilder(app, defaultHandler);
routeBuilder.Routes.Add(new Route(new HelloRouter(), "hello/{name:alpha?}",
app.ApplicationServices.GetService<IInlineConstraintResolver>()));
routeBuilder.MapRoute("Track Package Route",
"package/{operation:regex(track|create|detonate)}/{id:int}");
var router = routeBuilder.Build();
app.UseRouter(router);
}
public class HelloRouter : IRouter
{
public VirtualPathData GetVirtualPath(VirtualPathContext context)
{
return null;
}
public Task RouteAsync(RouteContext context)
{
var name = context.RouteData.Values["name"] as string;
if (String.IsNullOrEmpty(name)) name="World";
var requestPath = context.HttpContext.Request.Path;
if (requestPath.StartsWithSegments("/hello", StringComparison.OrdinalIgnoreCase))
{
context.Handler = async c =>
{
await c.Response.WriteAsync($"Hi, {name}!");
};
}
return Task.FromResult(0);
}
}
}
}
"Microsoft.AspNetCore.Diagnostics": "1.0.0"
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
namespace ConsoleApplication
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddRouting();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseDeveloperExceptionPage();
app.UseStatusCodePages(/*context=>{
throw new Exception($"Page return status code: {context.HttpContext.Response.StatusCode}");
}*/);
var defaultHandler = new RouteHandler(
c => c.Response.WriteAsync($"Default handler! Route values: {string.Join(", ", c.GetRouteData().Values)}")
);
var routeBuilder = new RouteBuilder(app, defaultHandler);
routeBuilder.Routes.Add(new Route(new HelloRouter(), "hello/{name:alpha?}",
app.ApplicationServices.GetService<IInlineConstraintResolver>()));
routeBuilder.MapRoute("Track Package Route",
"package/{operation:regex(track|create|detonate)}/{id:int}");
var router = routeBuilder.Build();
app.UseRouter(router);
}
public class HelloRouter : IRouter
{
public VirtualPathData GetVirtualPath(VirtualPathContext context)
{
return null;
}
public Task RouteAsync(RouteContext context)
{
var name = context.RouteData.Values["name"] as string;
if (String.IsNullOrEmpty(name)) name = "World";
if (String.Equals(name, "error", StringComparison.OrdinalIgnoreCase))
{
throw new ArgumentException("Hate errors! Won't say Hi!");
}
var requestPath = context.HttpContext.Request.Path;
if (requestPath.StartsWithSegments("/hello", StringComparison.OrdinalIgnoreCase))
{
context.Handler = async c =>
{
await c.Response.WriteAsync($"Hi, {name}!");
};
}
return Task.FromResult(0);
}
}
}
}
This is part of the .NET Core and VS Code series, which contains:namespace CodeHelloWorldI then go to the Debug icon and click it.
{
public class Program {
static void Main(string[] args) {
Console.WriteLine("Hello World!");
}
}
}
{
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceRoot}/bin/Debug/netcoreapp1.0/Code Hello World.dll",
"args": [],
"cwd": "${workspaceRoot}",
"externalConsole": false,
"stopAtEntry": false
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processId": 0
}
]
}you get something like {
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceRoot}/bin/Debug/<target-framework>/<project-name.dll>",
"args": [],
"cwd": "${workspaceRoot}",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": ".NET Core Launch (web)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceRoot}/bin/Debug/<target-framework>/<project-name.dll>",
"args": [],
"cwd": "${workspaceRoot}",
"stopAtEntry": false,
"launchBrowser": {
"enabled": true,
"args": "${auto-detect-url}",
"windows": {
"command": "cmd.exe",
"args": "/C start ${auto-detect-url}"
},
"osx": {
"command": "open"
},
"linux": {
"command": "xdg-open"
}
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processId": 0
}
]
}and a warning telling you to configure launch.json. It only works after changing the program property to '/bin/Debug/netcoreapp1.0/Code Hello World.dll' and, of course, the web and attach configuration sections are pointless.
In the last few days I've read several articles that all seem to say the same thing: computer algorithms we use today are biased towards wealthy white men, because they are made by companies in wealthy countries and predominantly by white male developers. Therefore they are inherently racist, misogynistic and wasteful. Nice journalistic metaphors were used such as: "Sea of dudes", "discriminatory code", "green algorithms", etc. I call bullshit!
Just when I thought I don't have anything else to add, I found new stuff for my Chrome browser extension.
The Date object in Javascript is not a primitive, it is a full fledged object, with a constructor and various instances, with methods that mutate their values. That means that the meaning of equality between two dates is ambiguous: what does it mean that date1 equals date2? That they are the same object or that they point to the same instance in time? In Javascript, it means they are the same object. Let me give you some code:var date1=new Date();
var date2=new Date(date1.getTime()); // now date2 points to the same moment in time as date1
console.log(date1==date2) // outputs "false"
date1=date2;
console.log(date1==date2) // outputs "true", date1 and date2 are pointing to the same object
I have created a Facebook page for the blog, so if you are tired by my Facebook ramblings and only need the updates for this blog, you can subscribe to it. You may find it here.
White to move. Can you draw? Can you win? What would you do? Try - I know it's fucking hard, but do it anyway - to think it through.
Clippy is back, thanks to this nice project. So what else could I have done than add it to my blog? Just go to Menu and choose your "Assistant".