Skip to content

Commit 9b787c4

Browse files
OliaGmairaw
andauthored
Desktop e-book: Chapter 3 (#17301)
* Add chapter 3 * Replace numbers with chapter names * Update to 83 Acrolinx score * Apply suggestions from code review Co-Authored-By: Maira Wenzel <[email protected]> * Update migrating-modern-desktop-applications.md * Update migrating-modern-desktop-applications.md * Remove trailing spaces * Apply suggestions from code review Co-Authored-By: Maira Wenzel <[email protected]> * Address comments * fix linting errors * add missing comma Co-authored-by: Maira Wenzel <[email protected]>
1 parent 07df066 commit 9b787c4

File tree

1 file changed

+337
-0
lines changed

1 file changed

+337
-0
lines changed
Lines changed: 337 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,337 @@
1+
---
2+
title: Migrating Modern Desktop Applications
3+
description: Everything you need to know about the migration process for modern desktop applications.
4+
ms.date: 09/16/2019
5+
---
6+
7+
# Migrating Modern Desktop Applications
8+
9+
In this chapter, we're exploring the most common issues and challenges you can
10+
face when migrating an existing application from .NET Framework to .NET Core.
11+
12+
A complex desktop application doesn't work in isolation and needs some kind of
13+
interaction with subsystems that may reside on the local machine or on a remote
14+
server. It will probably need some kind of database to connect as a persistence
15+
storage either locally or remotely. With the raise of Internet and
16+
service-oriented architectures, it's common to have your application
17+
connected to some sort of service residing on a remote server or in the cloud.
18+
You may need to access the machine file system to implement some functionality.
19+
Alternatively, maybe you're using a piece of functionality that resides inside
20+
a COM object outside your application, which is a common scenario if, for
21+
example, you're integrating Office assemblies in your app.
22+
23+
Besides, there are differences in the API surface that is exposed by .NET
24+
Framework and .NET Core, and some features that are available on .NET Framework
25+
aren't available on .NET Core. So, it's important for you to know and take them
26+
into account when planning a migration.
27+
28+
## Configuration files
29+
30+
Configuration files offer the possibility to store sets of properties that are
31+
read at run time and affect the behavior of our apps, such as where to locate a
32+
database or how many times to execute a loop. The beauty of this technique is
33+
that you can modify some aspects of the application without the need to recode
34+
and recompile. This comes in handy when, for example, the same app code runs on a
35+
development environment with a certain set of configuration values and in
36+
production with a different one.
37+
38+
### Configuration on .NET Framework
39+
40+
If you have a working .NET Framework desktop application, chances are you have an
41+
*app.config* file accessed through the <xref:System.Configuration.AppSettingsSection> class from the `System.Configuration` namespace.
42+
43+
Within the .NET Framework infrastructure, there's a hierarchy of configuration
44+
files that inherit properties from its parents. You can find a *machine.config* file
45+
that defines many properties and configuration sections that can be used
46+
or overridden in any descendant configuration file.
47+
48+
### Configuration on .NET Core
49+
50+
In the .NET Core world, there's no *machine.config* file. And even though you can continue
51+
to use the old fashioned <xref:System.Configuration> namespace, you may consider switching to the
52+
modern <xref:Microsoft.Extensions.Configuration>, which offers a good number of enhancements.
53+
54+
The configuration API supports the concept of configuration provider, which
55+
defines the data source to be used to load the configuration. There are different
56+
kinds of built-in providers, such as:
57+
58+
- In-memory .NET objects
59+
- INI files
60+
- JSON files
61+
- XML files
62+
- Command-line arguments
63+
- Environment variables
64+
- Encrypted user store
65+
66+
Or you can build your own.
67+
68+
The new configuration allows a list of name-value pairs that can be grouped
69+
into a multi-level hierarchy. Any stored value maps to a string, and there's
70+
built-in binding support that allows you to deserialize settings into a custom
71+
plain old CLR object (POCO) object.
72+
73+
The <xref:Microsoft.Extensions.Configuration.ConfigurationBuilder> object lets you add as many configuration providers you
74+
may need for your application, using a precedence rule to resolve preference.
75+
So, the last provider you add in your code will override the others. This is a
76+
great feature for managing different environments for execution since you can
77+
define different configurations for development, testing and production
78+
environments, and manage them on a single function inside your code.
79+
80+
### Migrating Configuration files
81+
82+
You can continue to use your existing app.config XML file. However, you could take this opportunity to migrate your configuration to benefit from the several enhancements made on .NET Core.
83+
84+
To migrate from an old-style *app.config* to a new configuration file,
85+
you should choose between an XML format and a JSON format.
86+
87+
If you choose XML, the conversion is straightforward. Since the content is the same, just rename the *app.config* file
88+
to a file with XML extension. Then, change the code that references AppSettings to use the `ConfigurationBuilder` class. This change should be easy.
89+
90+
If you want to use a JSON format and you don't want to migrate by hand,
91+
there's a tool called [dotnet-config2json](https://www.nuget.org/packages/dotnet-config2json/) available on .NET Core that
92+
can convert an *app.config* file to a JSON configuration file.
93+
94+
You may also come across some issues when using configuration sections that were
95+
defined in the *machine.config* file. For example, consider the following configuration:
96+
97+
```xml
98+
<configuration>
99+
<system.diagnostics>
100+
<switches>
101+
<add name="General" value="4" />
102+
</switches>
103+
<trace autoflush="true" indentsize="2">
104+
<listeners>
105+
<add name="myListener"
106+
type="System.Diagnostics.TextWriterTraceListener,
107+
System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
108+
initializeData="MyListener.log"
109+
traceOutputOptions="ProcessId, LogicalOperationStack, Timestamp, ThreadId, Callstack, DateTime" />
110+
</listeners>
111+
</trace>
112+
</system.diagnostics>
113+
</configuration>
114+
```
115+
116+
If you take this configuration to a .NET Core, you'll get an exception:
117+
118+
Unrecognized configuration section system.diagnostics
119+
120+
This exception occurs because that section and the assembly responsible for handling that section was
121+
defined in the *machine.config* file, which now doesn't exist.
122+
123+
To easily fix the issue, you can copy the section definition from your old
124+
machine.config to your new configuration file:
125+
126+
```xml
127+
<configSections>
128+
<section name="system.diagnostics"
129+
type="System.Diagnostics.SystemDiagnosticsSection,
130+
System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
131+
</configSections>
132+
```
133+
134+
## Accessing Databases
135+
136+
Almost every desktop application needs some kind of database. For desktop, it's
137+
common to find client-server architectures with a direct connection between the
138+
desktop app and the database engine. These databases can be local or remote
139+
depending on the need to share information between different users.
140+
141+
From the code perspective, there have been many technologies and frameworks to
142+
give the developer the possibility to connect, query, and update a database.
143+
144+
The most common examples of database you can find when talking about Windows
145+
Desktop application are Microsoft Access and Microsoft SQL Server. If you have
146+
more than 20 years of experience programming for the desktop, names like ODBC,
147+
OLEDB, RDO, ADO, ADO.NET, LINQ, and Entity Framework will sound familiar.
148+
149+
### ODBC
150+
151+
You can continue to use ODBC on .NET Core since Microsoft is providing the
152+
`System.Data.Odbc` library compatible with .NET Standard 2.0.
153+
154+
### OLE DB
155+
156+
[OLE DB](https://msdn.microsoft.com/library/ms722784(v=vs.85).aspx) has
157+
been a great way to access various data sources in a uniform manner. But it was
158+
based on COM, which is a Windows-only technology, and as such wasn't the best
159+
fit for a cross-platform technology such as .NET Core. It's also unsupported in
160+
SQL Server versions 2014 and later. For those reasons, OLE DB won't be
161+
supported by .NET Core.
162+
163+
### ADO.NET
164+
165+
You can still use ADO.NET from your existing desktop code on .NET Core. You
166+
just need to update some NuGet packages.
167+
168+
### EF Core vs. EF6
169+
170+
There are two currently supported versions of Entity Framework (EF), Entity Framework 6 (EF6) and EF Core.
171+
172+
The latest technology released as part of the .NET Framework world is Entity
173+
Framework, with 6.4 being the latest version. With the launch of .NET Core,
174+
Microsoft also released a new data access stack based on Entity Framework and
175+
called Entity Framework Core.
176+
177+
You can use EF 6.3 and EF Core from both .NET Framework and .NET Core. So, what
178+
are the decision drivers to help to decide between the two?
179+
180+
EF 6.3 is the first version of EF6 that can run on .NET Core and work
181+
cross-platform. In fact, the main goal of this release is to make it easier
182+
to migrate existing applications that use EF6 to .NET Core.
183+
184+
EF Core was designed to provide a developer experience similar to EF6. Most of
185+
the top-level APIs remain the same, so EF Core will feel familiar to developers
186+
who have used EF6.
187+
188+
Although compatible, there are differences on the implementation you should
189+
check before making a decision.
190+
For more information, see [Compare EF Core & EF6](/ef/efcore-and-ef6/).
191+
192+
The recommendation is to use EF Core if:
193+
194+
* The app needs the capabilities of .NET Core.
195+
* EF Core supports all of the features that the app requires.
196+
197+
Consider using EF6 if both of the following conditions are true:
198+
199+
* The app will run on Windows and .NET Framework 4.0 or later.
200+
* EF6 supports all of the features that the app requires.
201+
202+
### Relational databases
203+
204+
#### SQL Server
205+
206+
SQL Server has been one of the databases of choice if you were developing for
207+
the desktop some years ago. With the use of <xref:System.Data.SqlClient> in .NET
208+
Framework, you could access versions of SQL Server, which encapsulates
209+
database-specific protocols.
210+
211+
In .NET Core, you can find a new `SqlClient` class, fully compatible with the one
212+
existing in the .NET Framework but located in the <xref:Microsoft.Data.SqlClient>
213+
library. You just have to add a reference to the [Microsoft.Data.SqlClient](https://www.nuget.org/packages/Microsoft.Data.SqlClient/)
214+
NuGet package and do some renaming for the namespaces and everything should work as expected.
215+
216+
#### Microsoft Access
217+
218+
Microsoft Access has been used for years when the
219+
sophisticated and more scalable SQL Server wasn't needed. You can still connect
220+
to Microsoft Access using the <xref:System.Data.Odbc> library.
221+
222+
## Consuming services
223+
224+
With the raise of service-oriented architectures, desktop applications began to
225+
evolve from a client-server model to the three-layer approach. In the
226+
client-server approach, a direct database connection is established from the
227+
client holding the business logic usually inside a single EXE file. On the other
228+
hand, the three-layer approach establishes an intermediate service layer
229+
implementing business logic and database access allowing for better security,
230+
scalability, and reusability. Instead of working directly with datasets of data,
231+
the layer approach relies in a set of services implementing contracts and types
232+
objects as a way to implement data transfer.
233+
234+
If you have a desktop application using a WCF service and you want to migrate it
235+
to .NET Core, there are some things to consider.
236+
237+
The first thing is how to resolve the configuration to access the service.
238+
Because the configuration is different on .NET Core, you'll need to make
239+
some updates in your configuration file.
240+
241+
Second, you'll need to regenerate the service client with the new tools
242+
present on Visual Studio 2019. In this step, you must consider activating the
243+
generation of the synchronous operations to make the client compatible with your
244+
existing code.
245+
246+
After the migration, if you find that there are libraries you need that aren't
247+
present on .NET Core, you can add a reference to the [Microsoft.Windows.Compatibility](https://www.nuget.org/packages/Microsoft.Windows.Compatibility)
248+
NuGet package and see if the missing functions are there.
249+
250+
If you're using the <xref:System.Net.WebRequest> class to perform web service calls, you may
251+
find some differences on .NET Core. The recommendation is to use the
252+
System.Net.Http.HttpClient instead.
253+
254+
## Consuming a COM Object
255+
256+
Currently, there's no way to add a reference to a COM object from Visual Studio
257+
2019 to use with .NET Core. So, you have to manually modify the project file.
258+
259+
Insert a `COMReference` structure inside the project file like in the following example:
260+
261+
```xml
262+
<ItemGroup>
263+
<COMReference Include="MSHTML">
264+
<Guid>{3050F1C5-98B5-11CF-BB82-00AA00BDCE0B}\</Guid>
265+
<VersionMajor>4</VersionMajor>
266+
<VersionMinor>0</VersionMinor>
267+
<Lcid>0</Lcid>
268+
<WrapperTool>primary</WrapperTool>
269+
<Isolated>false</Isolated>
270+
</COMReference>
271+
</ItemGroup>
272+
```
273+
274+
## More things to consider
275+
276+
Several technologies available to .NET Framework libraries aren't available for
277+
.NET Core. If your code relies on some of these technologies, consider
278+
the alternative approaches outlined in this section.
279+
280+
The [Windows Compatibility Pack](../../core/porting/windows-compat-pack.md) provides access to APIs that were previously
281+
available only for .NET Framework. It can be used on .NET Core and .NET Standard projects.
282+
283+
For more information on API compatibility, the CoreFX team maintains a list of
284+
behavioral changes/compat breaks and deprecated/legacy APIs at GitHub.
285+
<https://github.com/dotnet/corefx/wiki/ApiCompat>)
286+
287+
### AppDomains
288+
289+
Application domains (AppDomains) isolate apps from one another. AppDomains
290+
require runtime support and are expensive. Creating additional
291+
app domains isn't supported. For code isolation, we recommend separate
292+
processes or using containers as an alternative. For the dynamic loading of
293+
assemblies, we recommend the new <xref:System.Runtime.Loader.AssemblyLoadContext> class.
294+
295+
To make code migration from .NET Framework easier, .NET Core exposes some of
296+
the AppDomain API surface. Some of the APIs function normally (for
297+
example, <xref:System.AppDomain.UnhandledException?displayProperty=nameWithType>), some members do nothing (for
298+
example, <xref:System.AppDomain.SetCachePath%2A>), and some of them throw
299+
<xref:System.PlatformNotSupportedException> (for example, <xref:System.AppDomain.CreateDomain%2A>).
300+
301+
### Remoting
302+
303+
.NET Remoting was used for cross-AppDomain communication, which is no longer
304+
supported. Also, Remoting requires runtime support, which is expensive to
305+
maintain. For these reasons, .NET Remoting isn't supported on .NET Core.
306+
307+
For communication across processes, you should consider inter-process
308+
communication (IPC) mechanisms as an alternative to Remoting, such as
309+
the <xref:System.IO.Pipes?displayProperty=nameWithType> or the <xref:System.IO.MemoryMappedFiles.MemoryMappedFile> class.
310+
311+
Across machines, use a network-based solution as an alternative. Preferably, use
312+
a low-overhead plaintext protocol, such as HTTP. The Kestrel web server, the
313+
web server used by ASP.NET Core, is an option here.
314+
315+
### Code Access Security (CAS)
316+
317+
Sandboxing, which relies on the runtime or the framework to constrain which
318+
resources a managed application or library uses or runs, isn't supported on .NET
319+
Core.
320+
321+
Use security boundaries that are provided by the operating system, such as
322+
virtualization, containers, or user accounts for running processes with the
323+
minimum set of privileges.
324+
325+
### Security Transparency
326+
327+
Similar to CAS, Security Transparency separates sandboxed
328+
code from security critical code in a declarative fashion but is no longer
329+
supported as a security boundary.
330+
331+
Use security boundaries that are provided by the operating system, such as
332+
virtualization, containers, or user accounts for running processes with the
333+
least set of privileges.
334+
335+
>[!div class="step-by-step"]
336+
>[Previous](whats-new-dotnet-core.md )
337+
>[Next](windows-migration.md)

0 commit comments

Comments
 (0)