Friday, June 29, 2018

TFS Build Agent - SSL certificate problem: unable to get local issuer certificate

After upgrading to a new TFS server and going full HTTPS, our git based builds started to fail with the following error message:

2018-06-12T21:28:45.8463514Z ##[command]git init "D:\Builds\dev-agent-1\_work\5\s"

2018-06-12T21:28:45.9154418Z Initialized empty Git repository in D:/Builds/dev-agent-1/_work/5/s/.git/

2018-06-12T21:28:45.9219662Z ##[command]git remote add origin https://tfs/DefaultCollection/_git/Sample

2018-06-12T21:28:45.9821910Z ##[command]git config gc.auto 0

2018-06-12T21:28:46.0407163Z ##[command]git config --get-all http.https://tfs/DefaultCollection/_git/Sample.extraheader

2018-06-12T21:28:46.0994413Z ##[command]git config --get-all http.proxy

2018-06-12T21:28:46.1508406Z ##[command]git -c http.extraheader="AUTHORIZATION: bearer ********" fetch --tags --prune --progress --no-recurse-submodules origin

2018-06-12T21:28:46.3636860Z fatal: unable to access 'https://tfs/DefaultCollection/_git/Sample/': SSL certificate problem: unable to get local issuer certificate

2018-06-12T21:28:46.3988694Z ##[error]Git fetch failed with exit code: 128

2018-06-12T21:28:46.4040002Z ##[section]Finishing: Get Sources

The SSL certificate we are using is based on a corporate root certificate. This root certificate is stored in the certificate store on all the servers .Any application written to use the Windows crypto APIs will have access to that root certificate, and will consider your TFS deployment to be trusted.

Unfortunately, Git for Windows (git.exe) uses OpenSSL for its crypto stack, and the Git for Windows distribution includes a set of trusted root certificates in a simple text file. As our root certificate is not in this set, we’ll get the error above.

An easy workaround we used at first was to add the following configuration setting on the global git config available at c:\programdata\git

[http] sslVerify=false

As this globally disables TLS(/SSL) certificate verification, it is not a solution I would recommend. This defeats the purpose of introducing SSL in the first place.

We’ll have to find a better solution, but we’ll leave that for another blog post…

Thursday, June 28, 2018

ASP.NET - Sharing state between Action Filters and Controllers

The support for ActionFilters in ASP.NET MVC and Web Api gives you a nice execution pipeline to run code before or after specific stages in the request processing pipeline:

The request is processed through Authorization Filters, Resource Filters, Model Binding, Action Filters, Action Execution and Action Result Conversion, Exception Filters, Result Filters, and Result Execution. On the way out, the request is only processed by Result Filters and Resource Filters before becoming a response sent to the client.

They are a great fit for a lot of use cases, like validation, caching, … and allow you to have an AOP like approach in your controllers. Their are 2 things I find annoying about the usage of ActionFilters:

  1. They introduce an extra layer of abstraction with some hidden magic. It is not always clear what’s going on the request pipeline and what happened in a specific filter.
  2. It is not easy to share state between your action filter and your controller (which can be useful sometimes).

Recently I discovered a great trick that solves the problems above.

Did you know that a controller is also a filter – as it implements both IActionFilter and IAsyncActionFilter interfaces, you can override the related methods and turn your controller into an action filter?

Wednesday, June 27, 2018

NHibernate Immutable Types

To prevent that changes to your objects end up accidently into your database, NHibernate supports type immutability.

This is something you can set at the ClassMap level(if you are using the mapping by code):

With Fluent Nhibernate, you have to use the ReadOnly property:

Remark: Using this property makes sure that the objects that you retrieve are read-only, so you cannot UPDATE them. However, it does NOT prevent the creation of new records or even the deletion of existing records in the database.

Tuesday, June 26, 2018

OData Query error: The query specified in the URI is not valid. The limit of '0' for Top query has been exceeded. The value from the incoming request is '100'

After configuration my OData service, I tried to do a first call by using a $top parameter to get the first 100 results. However this didn’t turned out to a big success. Instead of some data, I got the following error message back:

{"error":{"code":"","message":"The query specified in the URI is not valid. The limit of '0' for Top query has been exceeded. The value from the incoming request is '100'.","innererror":{"message":"The limit of '0' for Top query has been exceeded. The value from the incoming request is '100'.","type":"Microsoft.OData.ODataException","stacktrace":"   at System.Web.OData.Query.Validators.TopQueryValidator.Validate(TopQueryOption topQueryOption, ODataValidationSettings validationSettings)\r\n   at System.Web.OData.Query.TopQueryOption.Validate(ODataValidationSettings validationSettings)\r\n   at System.Web.OData.Query.Validators.ODataQueryValidator.Validate(ODataQueryOptions options, ODataValidationSettings validationSettings)\r\n   at System.Web.OData.Query.ODataQueryOptions.Validate(ODataValidationSettings validationSettings)\r\n   at System.Web.OData.EnableQueryAttribute.ValidateQuery(HttpRequestMessage request, ODataQueryOptions queryOptions)\r\n   at System.Web.OData.EnableQueryAttribute.ExecuteQuery(Object response, HttpRequestMessage request, HttpActionDescriptor actionDescriptor, ODataQueryContext queryContext)\r\n   at System.Web.OData.EnableQueryAttribute.OnActionExecuted(HttpActionExecutedContext actionExecutedContext)"}}}

Since Web API OData V6.0.0 you need to explicitly enable query options. This can be done globally in the WebApiConfig.Register(HttpConfiguration config):

Monday, June 25, 2018

TFS Build error - System.InvalidCastException: Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.Web.Administration.Interop.IAppHostWritableAdminManager'.

After replacing one of our build servers, we got the following error when trying to execute a custom XAML build Workflow activity:

System.InvalidCastException: Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.Web.Administration.Interop.IAppHostWritableAdminManager'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{FA7660F6-7B3F-4237-A8BF-ED0AD0DCBBD9}' failed due to the following error: Interface not registered (Exception from HRESULT: 0x80040155).

at Microsoft.Web.Administration.ConfigurationManager.CreateAdminManager[TClass,TInterface](WebConfigurationMap webConfigMap, Boolean isAdminConfig)

at Microsoft.Web.Administration.ConfigurationManager.CreateConfiguration(WebConfigurationMap configMap, String configPathToEdit, Boolean isAdminConfig)

at Microsoft.Web.Administration.ConfigurationManager.GetConfiguration(String rawConfigurationPath, String cacheKey, Boolean isAdminConfig)

at Microsoft.Web.Administration.ServerManager.get_ApplicationPoolsSection()

at Microsoft.Web.Administration.ServerManager.get_ApplicationPools()

at Microsoft.Web.Administration.ServerManagerExtensions.TryGetAppPool(ServerManager serverManager, String appPoolName, ApplicationPool& result)

at Customer.TeamFoundation.Build.Workflow.Activities.ControlAppPool.InnerExecute(CodeActivityContext context)

This activity tries to talk to IIS on our test environment to stop and restart the application pool after installation. The reason why it failed is because this activity requires IIS installed on the build server to allow remote administration.

After installing it, our XAML builds turned all green again…

Friday, June 22, 2018

Razor View compilation in ASP.NET Core

Update 26/6/2018: It can happen that what I describe below lead to much longer build times. This is a know issue. More information here: https://www.danielcrabtree.com/blog/444/speed-up-compilation-of-asp-net-core-2-1-projects

One of the ways to increase the speed of your ASP.NET MVC applications was by enabling view compilation. By default Razor views are not pre-compiled leading to longer startup times. Another disadvantage is that errors in views were not detected until you are running in the browser. Enabling view compilation solves this all.

Here is how to enable this in ASP.NET MVC: https://www.codeproject.com/Articles/1169354/Pre-compiled-Razor-View-in-ASP-NET-MVC

The question is, can you do the same thing in ASP.NET Core MVC?

In ASP.NET Core MVC, this behavior is enabled when the Microsoft.AspNetCore.Mvc.Razor.ViewCompilation package is referenced. As the Microsoft.AspNetCore.All package pulls in this package, this behavior is enabled by default for all new projects. It can be further controlled by setting the < MvcRazorCompileOnPublish> property. 

More information: https://docs.microsoft.com/en-us/aspnet/core/mvc/views/view-compilation?view=aspnetcore-2.1

Thursday, June 21, 2018

Cookie lifetime in Chrome

While documenting our security and privacy policies for GDPR, I got a question about the Windows Identity Foundation cookies created after logging into ADFS.

When looking in the Chrome Developer tools, we noticed that the Expires/Max-Age setting was set to 1969-12-31…:

image

We were wondering why this strange date? When I opened the same site in Edge, I saw the following in the Edge Developer Tools:

image

The cookie lifetime is set to Session, which makes more sense. Probably the Chrome Developer Tools are showing a minimum date when the cookie lifetime is linked to the session.

Kind of confusing…

Wednesday, June 20, 2018

ASP.NET Web API OData error: ValueFactory attempted to access the Value property of this instance.

After following the tutorial here; https://docs.microsoft.com/en-us/aspnet/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/create-an-odata-v4-endpoint I got the following error when I tried to run the OData endpoint:

System.InvalidOperationException was caught

  HResult=-2146233079

  Message=ValueFactory attempted to access the Value property of this instance.

  Source=mscorlib

  StackTrace:

       at System.Lazy`1.CreateValue()

       at System.Lazy`1.LazyInitValue()

       at System.Lazy`1.get_Value()

       at System.Web.Http.Dispatcher.DefaultHttpControllerSelector.GetControllerMapping()

       at System.Web.Http.Routing.AttributeRoutingMapper.AddRouteEntries(SubRouteCollection collector, HttpConfiguration configuration, IInlineConstraintResolver constraintResolver, IDirectRouteProvider directRouteProvider)

       at System.Web.Http.Routing.AttributeRoutingMapper.<>c__DisplayClass2.<>c__DisplayClass4.<MapAttributeRoutes>b__1()

       at System.Web.Http.Routing.RouteCollectionRoute.EnsureInitialized(Func`1 initializer)

       at System.Web.Http.Routing.AttributeRoutingMapper.<>c__DisplayClass2.<MapAttributeRoutes>b__0(HttpConfiguration config)

       at System.Web.Http.HttpConfiguration.ApplyControllerSettings(HttpControllerSettings settings, HttpConfiguration configuration)

       at System.Web.Http.Controllers.HttpControllerDescriptor.InvokeAttributesOnControllerType(HttpControllerDescriptor controllerDescriptor, Type type)

       at System.Web.Http.Controllers.HttpControllerDescriptor.InvokeAttributesOnControllerType(HttpControllerDescriptor controllerDescriptor, Type type)

       at System.Web.Http.Controllers.HttpControllerDescriptor.Initialize()

       at System.Web.Http.Controllers.HttpControllerDescriptor..ctor(HttpConfiguration configuration, String controllerName, Type controllerType)

       at System.Web.Http.Dispatcher.DefaultHttpControllerSelector.InitializeControllerInfoCache()

       at System.Lazy`1.CreateValue()

       at System.Lazy`1.LazyInitValue()

       at System.Lazy`1.get_Value()

       at System.Web.Http.Dispatcher.DefaultHttpControllerSelector.GetControllerMapping()

       at System.Web.OData.Routing.Conventions.AttributeRoutingConvention.<>c__DisplayClass1.<.ctor>b__0(HttpConfiguration config)

       at System.Web.Http.Routing.AttributeRoutingMapper.<>c__DisplayClass2.<MapAttributeRoutes>b__0(HttpConfiguration config)

       at System.Web.Http.HttpConfiguration.EnsureInitialized()

       at System.Web.Http.GlobalConfiguration.Configure(Action`1 configurationCallback)

This was an error message I’ve never seen before, so I had no immediate clue about what’s going on. Here is how our API configuration looks like:

We found out that by changing the order in which we register the routes solved the problem:

Tuesday, June 19, 2018

Angular 5 Build issues - Cannot find module 'webpack/lib/dependencies/ContextElementDependency'

After upgrading to Node.js version 8 on our build server, one of our development teams contacted me because their build started to fail. Here is the error they got when running ‘ng build’:

2018-06-14T06:20:11.8790352Z ##[section]Starting: ng build

2018-06-14T06:20:11.9073421Z ==============================================================================

2018-06-14T06:20:11.9073421Z Task         : npm

2018-06-14T06:20:11.9073421Z Description  : Run an npm command

2018-06-14T06:20:11.9083182Z Version      : 0.2.22

2018-06-14T06:20:11.9083182Z Author       : Microsoft Corporation

2018-06-14T06:20:11.9083182Z Help         : [More Information](https://go.microsoft.com/fwlink/?LinkID=613746)

2018-06-14T06:20:11.9083182Z ==============================================================================

2018-06-14T06:20:15.5560039Z [command]C:\Program Files\nodejs\npm.cmd config list

2018-06-14T06:20:17.1849642Z ; cli configs

2018-06-14T06:20:17.1849642Z metrics-registry = "https://registry.npmjs.org/"

2018-06-14T06:20:17.1849642Z scope = ""

2018-06-14T06:20:17.1849642Z user-agent = "npm/5.6.0 node/v8.11.2 win32 x64"

2018-06-14T06:20:17.1849642Z

2018-06-14T06:20:17.1849642Z ; builtin config undefined

2018-06-14T06:20:17.1859408Z prefix = "C:\\Users\\AppData\\Roaming\\npm"

2018-06-14T06:20:17.1859408Z

2018-06-14T06:20:17.1859408Z ; node bin location = C:\Program Files\nodejs\node.exe

2018-06-14T06:20:17.1859408Z ; cwd = D:\b\3\_work\8\s\BBM

2018-06-14T06:20:17.1859408Z ; HOME = C:\Users\

2018-06-14T06:20:17.1859408Z ; "npm config ls -l" to show all defaults.

2018-06-14T06:20:17.1869174Z

2018-06-14T06:20:17.2357474Z [command]C:\Program Files\nodejs\npm.cmd run ng build

2018-06-14T06:20:20.5014978Z

2018-06-14T06:20:20.5014978Z > BBM@0.0.0 ng D:\b\3\_work\8\s\BBM

2018-06-14T06:20:20.5171234Z > ng "build"

2018-06-14T06:20:20.5171234Z

2018-06-14T06:20:30.8837324Z Cannot find module 'webpack/lib/dependencies/ContextElementDependency'

2018-06-14T06:20:30.8837324Z Error: Cannot find module 'webpack/lib/dependencies/ContextElementDependency'

2018-06-14T06:20:30.8837324Z     at Function.Module._resolveFilename (module.js:547:15)

2018-06-14T06:20:30.8837324Z     at Function.Module._load (module.js:474:25)

2018-06-14T06:20:30.8837324Z     at Module.require (module.js:596:17)

2018-06-14T06:20:30.8837324Z     at require (internal/module.js:11:18)

2018-06-14T06:20:30.8837324Z     at Object.<anonymous> (D:\b\3\_work\8\s\BBM\node_modules\@ngtools\webpack\src\plugin.js:8:34)

2018-06-14T06:20:30.8837324Z     at Module._compile (module.js:652:30)

2018-06-14T06:20:30.8837324Z     at Object.Module._extensions..js (module.js:663:10)

2018-06-14T06:20:30.8837324Z     at Module.load (module.js:565:32)

2018-06-14T06:20:30.8837324Z     at tryModuleLoad (module.js:505:12)

2018-06-14T06:20:30.8837324Z     at Function.Module._load (module.js:497:3)

2018-06-14T06:20:30.9325624Z npm ERR! code ELIFECYCLE

2018-06-14T06:20:30.9325624Z npm ERR! errno 1

2018-06-14T06:20:30.9345156Z npm ERR! BBM@0.0.0 ng: `ng "build"`

2018-06-14T06:20:30.9345156Z npm ERR! Exit status 1

2018-06-14T06:20:30.9345156Z npm ERR!

2018-06-14T06:20:30.9354922Z npm ERR! Failed at the BBM@0.0.0 ng script.

2018-06-14T06:20:30.9354922Z npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

2018-06-14T06:20:30.9520944Z

2018-06-14T06:20:30.9520944Z npm ERR! A complete log of this run can be found in:

2018-06-14T06:20:30.9520944Z npm ERR!     C:\Users\AppData\Roaming\npm-cache\_logs\2018-06-14T06_20_30_933Z-debug.log

2018-06-14T06:20:31.3720324Z ##[error]npm failed with error: C:\Program Files\nodejs\npm.cmd failed with return code: 1

2018-06-14T06:20:31.3720324Z ##[section]Finishing: ng build

Here are the steps we took to fix it:

  • Step 1  - Deleted the node modules from the build folder
  • Step 2 – Removed the existing package-lock.json
  • Step 3 - Run npm install
  • Step 4 – Check in the newly created package-lock.json

After doing that, the build started to work again. (My love/hate relationship with NPM continues…Smile)

Monday, June 18, 2018

Azure–Single Instance VMs with 99.9% SLA

When Microsoft introduced their IAAS offering on Azure, the general rule to have a 99.9% SLA was to have at least 2 VMs provisioned. Most of my customers who I talk to today remember this rule and think that it still applies. Where in fact, there is since 2016 an option to provide a single instance VM and have the 99.9% SLA guarantee too!

The biggest requirement to achieve the 99.9% SLA guarantee for a single instance VM is to use Premium Storage. Premium Storage offers a much higher level of availability and performance with 5,000 IOPS per disk, versus 500 IOPS per disk with Standard Storage. The way Premium storage offers this is by utilizing SSD storage drives within the data center that are located on the same server hardware where the VM is running. Premium storage also offers a much higher throughput rate per disk of 2 Gbps.

Why should I still prefer multi-instance VMs?

It can still be adventagous to use a multi-instance VM configuration, because the SLA is a higher(99.95%). And of course your architecture is easier to scale horizontally.

More information: Azure SLA for Virtual Machines

Friday, June 15, 2018

Play with Kubernetes classroom

If you want to learn Kubernetes in a quick and easy way, have a look at https://training.play-with-kubernetes.com/

From the website:

The Play with Kubernetes classroom is a new site provided by Docker that helps you get hands-on experience using Kubernetes. We provide a workshop that will allow you, in the browser, to follow a Kubernetes tutorial without having to install a single thing.

Kubernetes Hands-on Workshop

image

Thursday, June 14, 2018

C#–Task vs ValueTask

The combination of async/await with the power of the TPL(Task Parallel Library) makes async programming in .NET a breeze. The only disadvantage of using the Task based programming model, is that it’s like a virus that starts to spread all around your code. Since Task (Task) is a reference type, returning Task object from async method means allocating it on heap every time. And this is needed in many cases.

In these cases where the async method returns a result immediately or completes synchronously, this allocation is unnecessary and can become costly. To avoid this extra allocation a ValueTask structure was added to .NET 4.7.

The compiler doesn’t care if your async method returns a Task or ValueTask, so there are completely interchangeable;

So why shouldn’t I switch to ValueTask everywhere?

There are some tradeoffs you must take into consideration before using ValueTask. ValueTask is a value type with 2 fields. The Task is a reference type with just one field. When you use ValueTask we have more data to handle and take care of. If such method is awaited within an async method, the state machine for that async method will be larger as well, because storing the whole structure, in general, requires more space than storing a single reference.

Conclusion

The recommendation is to use Task as default return type, only after performance analysis, you should consider using ValueTask instead.

More information: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/async-return-types

Wednesday, June 13, 2018

Using Azure Container Instances to host ElasticSearch

As I’m doing a lot of demos using ElasticSearch, I like to use Azure Container Instances to spin up a new container image. To simplify the creation process, I’m using the Azure CLI in combination with the script below:

Remark: this is a copy of one of the scripts found here; https://github.com/markheath/aci-getting-started/blob/master/m1-01-elasticsearch.ps1

Tuesday, June 12, 2018

ElasticSearch–Wait for index refresh

By default when you index a document in ElasticSearch it only becomes available for search operations after a certain time.  This is because ElasticSearch will refresh shards that have changed only after a certain interval(by default 1 second).

If this is not the behavior you want,  you can control when changes are made visible by setting the refresh parameter to one of the following values:

Empty string or true
Refresh the relevant primary and replica shards (not the whole index) immediately after the operation occurs, so that the updated document appears in search results immediately. This should ONLY be done after careful thought and verification that it does not lead to poor performance, both from an indexing and a search standpoint.
wait_for
Wait for the changes made by the request to be made visible by a refresh before replying. This doesn’t force an immediate refresh, rather, it waits for a refresh to happen. Elasticsearch automatically refreshes shards that have changed every index.refresh_interval which defaults to one second. That setting is dynamic. Calling the Refresh API or setting refresh to true on any of the APIs that support it will also cause a refresh, in turn causing already running requests with refresh=wait_for to return.
false (the default)
Take no refresh related actions. The changes made by this request will be made visible at some point after the request returns.

In general it is recommended to not change this parameter unless you have a very good reason to wait for the change to become visible. In that case prefer the usage of refresh=wait_for over refresh=true

More information: https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-refresh.html

Monday, June 11, 2018

Entity Framework Core 2.1 - Avoiding the n+1 issue

With the release of Entity Framework Core 2.1, the team did some changes to the query translation to avoid executing n+1 SQL queries.

The n+1 problem occurs when you first fetch the some root data and later on use a navigation property while looping through all results(for example when you project your domain model to a viewmodel to return it from an API call).

An example; the following query normally gets translated into one query for Customers, plus N (where “N” is the number of customers returned) separate queries for Orders:

To avoid the n+1 issue, you can optimize this query by buffering the results from the sub-query. To achieve this, you have to modify your query and add a ToList() in the right place:

An example; this time the query will be translated to only two SQL queries: One for Customers and the next one for Orders.

More information: https://blogs.msdn.microsoft.com/dotnet/2018/05/30/announcing-entity-framework-core-2-1/

Friday, June 8, 2018

NHibernate–Persist vs Save

While reviewing some code today I noticed that a developer was using the NHibernate session.PersistAsyc() method to save an entity in the database. I always used the session.SaveAsync() method so I was kinda intrigued about the difference between the two.

Let’s first talk about how they are the same; both methods make a transient instance persistent. This means that a new object created somewhere inside your code will be inserted into the database using an INSERT statement.

The picture below explains the different states of an NHibernate object quite well:

nhibernatestates

The differences

Ok, now we know in which way they are the same. How are they different then?

  • The SaveAsync() method returns the persisted object whereas the PersistAsync() method returns nothing.
  • The PersistAsync() method doesn't guarantee that the identifier value will be assigned to the persistent instance immediately, the assignment might happen at flush time. This means that when calling the SaveAsync() method, the INSERT operation is executed immediatelly.
  • Calling SaveAsync() on a detached entity will result in a new INSERT statement whereas calling PersistAsync will throw an exception.
  • Calling PersistAsync() outside of transaction boundaries will do nothing whereas doing the same using SaveAsync will result in the execution of an INSERT statement.

If you know more differences, please feel free to share…

Thursday, June 7, 2018

MediatR and StructureMap–Using Generic NotificationHandlers.

One of our application is using a CQRS approach in combination with MediatR and StructureMap. Part of the application is rather straightforward and to avoid a lot of boilerplate code we would like to use a NotificationHandler that could handle generic events. Here is the code we had written:

However when we tried to register this using StructureMap nothing happened resulting in no event that was picked up by the NotificationHandler. Here is the registration code we had:

The problem is that it is one level of generic too deep to handle by StructureMap, so StructureMap has no clue on how to close this open generic. To solve this problem we can create our own registry convention:

As a last step we have to apply this convention when configuring StructureMap:

Wednesday, June 6, 2018

Issue building UWP apps: Error WMC1006: Cannot resolve Assembly or Windows Metadata file

A customer contacted me because they had errors building an UWP application on one of their build servers. Here are the related build logs:

MarkupCompilePass1:

  Creating directory "obj\x86\Release\intermediatexaml\".

App1\App1.csproj(0,0): Error WMC1006: Cannot resolve Assembly or Windows Metadata file 'Type universe cannot resolve assembly: System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a.'

D:\Builds\dev-agent-1\_work\76\s\App1\App1.csproj : XamlCompiler error WMC1006: Cannot resolve Assembly or Windows Metadata file 'Type universe cannot resolve assembly: System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a.'

  (Out) GeneratedCodeFiles: 'D:\Builds\dev-agent-1\_work\76\s\App1\obj\x86\Release\App.g.i.cs;D:\Builds\dev-agent-1\_work\76\s\App1\obj\x86\Release\App.g.cs'

  (Out) Compile: 'App.xaml.cs;MainPage.xaml.cs;Properties\AssemblyInfo.cs;D:\Builds\dev-agent-1\_work\76\s\App1\obj\x86\Release\App.g.i.cs;D:\Builds\dev-agent-1\_work\76\s\App1\obj\x86\Release\App.g.cs'

XamlPreCompile:

  D:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\Roslyn\csc.exe /noconfig /nowarn:2008,1701,1702 /nostdlib+ /platform:x86 /errorreport:prompt /warn:0 /define:TRACE;NETFX_CORE;WINDOWS_UWP;CODE_ANALYSIS /highentropyva+ /reference:"C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.ApplicationModel.Calls.CallsVoipContract\2.0.0.0\Windows.ApplicationModel.Calls.CallsVoipContract.winmd" /reference:"C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.ApplicationModel.SocialInfo.SocialInfoContract\2.0.0.0\Windows.ApplicationModel.SocialInfo.SocialInfoContract.winmd" /reference:"C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.ApplicationModel.StartupTaskContract\2.0.0.0\Windows.ApplicationModel.StartupTaskContract.winmd" /reference:"C:\Program Files (x86)\Windows Kits\10\References\10.0.16299.0\Windows.Devices.Custom.CustomDeviceContract\1.0.0.0\Windows.Devices.Custom.CustomDeviceContract.winmd" /reference:"C:\Program Files...

  Using shared compilation with compiler from directory: D:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\Roslyn

CSC(0,0): Error CS2001: Source file 'D:\Builds\dev-agent-1\_work\76\s\App1\obj\x86\Release\App.g.i.cs' could not be found.

CSC : error CS2001: Source file 'D:\Builds\dev-agent-1\_work\76\s\App1\obj\x86\Release\App.g.i.cs' could not be found. [D:\Builds\dev-agent-1\_work\76\s\App1\App1.csproj]

Done Building Project "D:\Builds\dev-agent-1\_work\76\s\App1\App1.csproj" (default targets) -- FAILED.

Done Building Project "D:\Builds\dev-agent-1\_work\76\s\App1.sln" (default targets) -- FAILED.

Build FAILED.

On our local systems everything worked fine and even on our Hosted Build Server on VSTS, we were able to build without any issues. We were quite confident the problem was related to the targeted UWP version as with older UWP apps we didn’t had any issues.

After contacting Microsoft they told us to switch our build server from Windows Server 2012R2 to 2016. After upgrading everything started to work!

Tuesday, June 5, 2018

NHibernate auto-import

By default NHibernate supports the auto-import feature. This allows you to use unqualified class names in the HQL query language. This feature can become a problem if you have 2 classes with the same name (e.g. ExampleClass) but living in a different namespace(e.g. Example1Namespace,Example2Namespace).

If you try to initialize your SessionFactory, you will end up with the following error message:

"duplicate import:

Example refers to both

Example2Namespace.ExampleClass, Example2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null  and

Example1Namespace.ExampleClass, Example1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

(try using auto-import=\"false\")"

As a solution, you can set auto-import=false in your NHibernate mapping files.

Remark: This however does introduce another issue – it forces you to use the fully qualified name of these classes in HQL queries.

Monday, June 4, 2018

Mobile vs Web: https://whatwebcando.today/

With the introduction of Progressive Web Apps, the discussion if web applications can and will replace native mobile applications has started all over again.

To feed the discussion, have a look at https://whatwebcando.today/ and decide for yourself if you can rely on the Web Platform features to build your next mobile application…

image

Friday, June 1, 2018

Attempt by security transparent method 'System.Web.Http.GlobalConfiguration.get_Configuration()' to access security critical type 'System.Web.Http.HttpConfiguration' failed.

After doing a new deploy on our IIS server, we got the following error when we tried to start our ASP.NET MVC application:

System.TypeAccessException: Attempt by security transparent method 'System.Web.Http.GlobalConfiguration.get_Configuration()' to access security critical type 'System.Web.Http.HttpConfiguration' failed.

image

This rather obscure error didn’t ring a bell. And the explanation was not very helpfull.

When we looked at what had changed between this version and a previous version of the application, we noticed that WebApi was added to the solution. The NuGet package.config showed us that one of the packages had a rather different version:

<package id="Microsoft.AspNet.WebApi.Client" version="5.2.6" targetFramework="net47" />

<package id="Microsoft.AspNet.WebApi.Core" version="5.2.6" targetFramework="net47" />

<package id="Microsoft.AspNet.WebApi.WebHost" version="4.0.30506" targetFramework="net47" />

So we did a package upgrade to align all packages to the same version. After doing that, the error message disappeared.