If you are a Visual Studio user you can get .NET Core 3.0 by installing at least Visual Studio 16.4. For those not using Visual Studio, you can download and install .NET Core 3.1 SDK from here. As with previous versions, the SDK is available for Windows, Linux, and Mac.
After installation is complete you can run the following command from a command prompt to see all the versions of the .NET Core SDK you have installed.
dotnet --list-sdks
You should see 3.1.100 listed at a minimum.
Project File Changes
Right-click on the project and select Edit projectName.csproj.
Change the TargetFramework to netcoreapp3.1.
Before:
<TargetFramework>netcoreapp3.0</TargetFramework>
After
<TargetFramework>netcoreapp3.1</TargetFramework>
Next, update all your packages to the new versions. This is going to vary greatly based on your project. This can be done manually in the csproj file or via the NuGet UI if you are using Visual Studio. The following are the changes from the sample project.
The move from 3.0 to 3.1 is drop-dead simple which is not surprising since it has only been a few months since the release of 3.0. It is important to move to 3.1 as soon as you can since it is the long term service version and will be supported for at least the next 3 years where 3.0 will lose support within months.
This week we are going to add a Razor Pages project that will utilize the API we created a few weeks ago. This post is part of the revamp of my ASP.NET Core Basics repo that I kicked off when .NET Core 3.0 was released. For details on how we got to the current point in the application check out the following posts.
The code before the changes in this post can be found in this GitHub repo.
Razor Pages Project
Add a new directory for the application and then in a terminal navigate to that directory. Then the following command can be used to create the new Razor Pages application.
dotnet new webapp
Next, use the following command to add the new project to the solution file which is in the root of the repo. Your filenames and paths could vary if you can’t using the same code of course.
For API access we are using NSwag to generate a client that our Razor Page application will use. For the actual creation of the API client see the following posts as this post will be skipping the actual client generation process.
With the client-generated and in our local Apis directory in the Razor Pages project we can now work on getting it configured and registered for use in our new project. First, open the apppsetting.json file and add a setting for the URL of our API, which is the ContactsApi value in the following sample.
Next, in the ConfigureServices function of the Startup class we need to register a HTTP Client for our API.
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages()
.AddNewtonsoftJson();
services.AddHttpClient<IContactsClient,
ContactsClient>(client =>
client.BaseAddress = new Uri(Configuration.GetSection("ContactsApi").Value));
}
Add Pages
Now that our API access is set up we need to create pages that will allow users to interact with the API. To start add a Contacts directory to the existing Pages directory so all of the pages that deal with interacting with the Contacts API will be together.
CAUTION the next bit may or may not be helpful. I wanted to generate the UI for the Contact pages instead of having to manually create them using the scaffolding, but it needs Entity Framework to work and this new project doesn’t use Entity Framework. This section is going to walk through adding a temporary reference to the API project, since it does use Entity Framework, in order to generate the related UI. Feel free to skip this part if you want to manually create your associated UI.
In the API project add the following temparary changes to the ContactsDbContext class.
Now we need to add a temporary reference to the API project from the Razor Pages project. To do this right-click on the Dependencies node in Razor Pages project and select Add Reference.
In the Projects section check the box for the API project and click OK.
Now with the above in place, we can scaffold our UI. Right-click on the folder where you want the resulting UI to live, the Pages/Contacts directory in our case. From the menu select Add > New Scaffolded Item.
On the dialog that shows we want to select Razor Pages using Entity Framework (CRUD) and then click Add.
On the next screen we will be selecting the Model class and Data context class from the API project for the entity we are generating the UI for and then clicking Add.
After a few seconds, all the pages we need to view, create, edit, and delete contacts will exist. Now that we have our pages generated we need to remove the reference to the API project. To do this expand the Dependencies > Projects node and right-click on the API project and select Remove.
Also, revert the changes we made to the DbContext above.
Now that the reference to the API project is gone the Razor Pages application won’t build. This is expected as it was using some classes from the API project. We are going to walk through the edits needed to fix the issues in the Index page in the Contacts directory, but the same type of changes will be needed in all the generated classes.
First, we need to change some usings. Remove any Entity Framework related usings. Then change any related to the Contacts API to instead reference the API client local to the project.
Before:
using Microsoft.EntityFrameworkCore;
using ContactsApi.Data;
using ContactsApi.Models;
After:
using Apis;
The other big item is to replace the injection of the Entity Framework DB Context with the API Client and update the related calls with calls to the API. The following is the IndexModel with the Entity Framework bits present.
public class IndexModel : PageModel
{
private readonly ContactsApi.Data.ContactsDbContext _context;
public IndexModel(ContactsApi.Data.ContactsDbContext context)
{
_context = context;
}
public IList<Contact> Contact { get;set; }
public async Task OnGetAsync()
{
Contact = await _context.Contacts.ToListAsync();
}
}
And here is the end result using the API Client.
public class IndexModel : PageModel
{
private readonly IContactsClient _client;
public IndexModel(IContactsClient client)
{
_client = client;
}
public IList<Contact> Contact { get;set; }
public async Task OnGetAsync()
{
Contact = (await _client.GetContactsAsync()).ToList();
}
}
And as stated above this kind of thing would need to be repeated for the other generated pages.
END CAUTION
Add to Navigation Bar
Now that we have our pages created we need to add a way for the user to get to them. To do this we are going to add a Contacts option to the navigation bar. Open the Pages/Shared/_Layout.cshtml file. The easiest way to locate where the change needs to go is to search for the text of one of the existing navigation links. The following is the links section with the new items added.
Using Nswag’s generated client makes it super simple to connect an application to an API, not that doing it manually is hard per se. Most of this post ended up being about my detour to generate the UI in the client application. Was it worth it? I’m not sure. I guess either way it is nice to know it is an option when you have the Entity Framework data available.
Here is the code in the final state from this post.
No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions<TContext> object in its constructor and passes it to the base constructor for DbContext.
State of the Project
The project I was working on was an API that had a single model defined as the following.
public class Contact
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
}
And the DbContext looked like this.
public class ContactsDbContext : DbContext
{
public DbSet<Contact> Contacts { get; set; }
}
Finally the ConfigureServices function of Startup.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ContactsDbContext>(options =>
options.UseSqlite(Configuration.GetConnectionString("DefaultConnection")));
services.AddControllers();
}
The Error
At this point, I ran the following command from the command prompt to add a migration.
dotnet ef migrations add Initial
Which results in the following error.
Stay Calm, Read, and Fix
Don’t make the same mistake I did and runoff and double-check everything in your application. The yellow and red sections of the exception message tell you what the fix should be.
In the case of the application in question, I wanted to use the connection string setup in Startup.ConfigureServices. To do that, as the error states if you bother to read it, the DbContext needs a constructor added that takes a DbContextOptions and passes that value to the base class’ constructor like the following.
public ContactsDbContext(DbContextOptions<ContactsDbContext> options) : base(options)
{ }
Alternatively, if you aren’t to the point in your application that you want to get your database information from configuration you can override OnConfiguring in your DbContext and set your connection string there like the following.
I don’t recommend the second option, but since it is valid I feel like it needs to be included.
Wrapping Up
For me, this served as a good reminder to slow down and actually read errors even if they are a wall of text. Hopefully making myself write this post will help this lesson stick.
Last week was an unofficial kicked off a series of posts associated with a refresh of the ASP.NET Basics repo frequently reference in this blog to reflect the state of affairs now that .NET Core 3 has been released. The new repo is ASP.NET Basics Refresh because naming is hard.
This post is going to take the API project created last week for the Swagger/OpenAPI with NSwag and ASP.NET Core 3 post and replace the generated data with a database using Entity Framework Core. If you want to follow along with this post the files before any changes can be found here.
Add NuGet Packages
Entity Framework Core is no longer included with .NET Core by default so we install a couple of NuGet packages to get started. I’m going to give the .NET CLI command, but this could also be done using the Visual Studio NuGet Package Manager UI. This post will also be using SQLite, but Entity Framework Core supports multiple databases you would need to install the package for the database you are interested in using.
Here are the commands to install the package we will be using. This is also assuming your terminal is in the same directory as the project file.
Just as a reminder we already have a Contact class in the Models directory with the following definition.
public class Contact
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
}
Next, I added a Data directory to the project and then added a new class called ContactedDbContext. The DbContext only exposes one DbSet for Contacts.
public class ContactsDbContext : DbContext
{
public DbSet<Contact> Contacts { get; set; }
public ContactsDbContext(DbContextOptions<ContactsDbContext> options)
: base(options)
{ }
}
Configuration for the Connection String
In the appsettings.json file, which is where the application will pull configuration from by default, we are going to add a connection strings section to hold our default connection. The following is my full appsettings.json with the connection string for SQLite. If you are using a different database provider your connection string could be drastically different.
Open Startup.cs and in the ConfigureServices function, we are going to use the AddDbContext extension method to add our new DbContext and tell it to use SQLite with the connection string from our appsettings.json. The following is the full function with the first two lines being the ones we added.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ContactsDbContext>(options =>
options.UseSqlite(Configuration.GetConnectionString("DefaultConnection")));
services.AddControllers();
services.AddOpenApiDocument(document =>
document.PostProcess = d => d.Info.Title = "Contacts API");
}
For this bit, we are going to head back to the command line open to the directory that contains the csproj for the project we are working with. The first thing we need to do is to install the Entity Framework Core Tool using the following command which will install the tool globally.
dotnet tool install --global dotnet-ef
Next, we will create a migration called Initial that output in the Data/Migrations directory using the following command.
dotnet ef migrations add Initial -o Data/Migrations
Now that we have a migration lets use it to create our database. Note that the same command will be used in the future when applying migrations to an existing database.
If you are using the code from GitHub at this point you will need to delete the ContactsController as it is going to be recreated using Visual Studio’s tooling.
Right-click on the directory where the controller should be created, the Controllers directory in the example, and select Add and then Controller.
On the dialog that pops up, we want to select API Controller with actions, using Entity Framework and then click Add.
On the next screen specify the model class, data context, and controller name before clicking Add. In the sample case, we are going to use our Contact class for the model, ContactDbContext for the data context to generate a controller named ContactController.
After clicking add the requested controller will be generated with all the functions needed for CRUD operations for the selected model class. The code for our sample controller can be found here.
Try it out
Running the application and hitting our swagger UI with the help of NSwag we can see all the options our API has available and even try them out which will now hit our application’s database.
Another great option to test out APIs which has a lot of really great features is Postman. Either option will allow you to try out your API without having to build a client.
Wrapping Up
Hopefully, this post will help you get a jump start on integrating Entity Framework Core in your ASP.NET Core 3 applications. As a reminder Entity Framework Core supports a lot of different database providers. If you have any question I recommend checking Microsoft’s official docs on Getting Started with Entity Framework Core.
The code with all the above changes can be found here.
On September 23rd .NET Core 3.0 was released including ASP.NET Core 3.0 and Entity Framework Core 3.0. This post will be taking the Contacts project used in the ASP.NET Basics series and migrating it from .NET Core 2.2 to .NET Core 3.0. Most of the information used for this migration comes from the Microsoft docs which will cover way more scenarios than this post will.
The code before any changes can be found in this GitHub repo. A reminder that the Contacts project is the only project being updated with this post the projects in the repo will remain on ASP.NET Core 2.2 for now.
Installation
If you are a Visual Studio user you can get .NET Core 3.0 by installing at least Visual Studio 16.3. For those not using Visual Studio, you can download and install .NET Core 3.0 SDK from here. As with previous versions, the SDK is available for Windows, Linux, and Mac.
After installation is complete you can runt the following command from a command prompt to see all the versions of the .NET Core SDK you have installed.
dotnet --list-sdks
You should see 3.0.100 listed. If you are like me you might also see a few preview versions of the SDK that can be uninstalled at this point.
Project File Changes
Right-click on the project and select Edit projectName.csproj.
The packages section has a lot of changes. Microsoft.AspNetCore.App is now gone and part of .NET Core without needing a specific reference. The other thing to note is that Entity Framework Core is no longer “in the box” so you will see a lot of references add to make Entity Framework Core usable.
The last thing to note is that Swashbuckle doesn’t have a final version ready for .NET Core 3 so you will have to make sure you are using version 5 rc2 at a minimum.
The following is my full project file for reference.
In Program.cs some changes to the way the host is constructed. The over version may or may not have worked, but I created a new app and pulled this out of it just to make sure I’m using the current set up.
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
namespace Contacts
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
Startup Changes
In Startup.cs we have quite a few changes to make. As long as you haven’t do any customization in the constructor you can replace it with the following.
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
Next, they type on the configuration property changed from IConfigurationRoot to IConfiguration.
Before:
public IConfigurationRoot Configuration { get; }
After:
public IConfiguration Configuration { get; }
Moving on to the ConfigureServices function has a couple of changes to make. The first is a result of updating to the newer version of the Swagger package where the Info class has been replaced with OpenApiInfo.
Before:
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Title = "Contacts API", Version = "v1"});
});
After:
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Contacts API", Version = "v1" })
});
Next, we are going to move from using UserMvc to the new AddControllersWithViews which is one of the new more targeted ways to add just the bits of the framework you need.
Now in the Configure function, the function signature needs to be updated and the logging factory bits removed. If you do need to configure logging that should be handled as part of the HostBuilder.
Before:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
After:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
For the next set of changes, I’m just going to show the result and not the before. The UseCors may or may not apply but the addition of UserRouting and the replacement of UseMvc with UserEndpoint will if you want to use the new endpoint routing features.
The only other change I had was the removal of @using Microsoft.AspNetCore.Http.Authentication in a few cshtml files related to login.
Wrapping Up
The migration from 2.2 to 3.0 is a bit more involved than the move from 2.1 to 2.2, but that isn’t surprising with all the changes in this release. Remember to check out the official migration guide for more details.
The code for the Contacts project after the above changes can be found on GitHub.
I’m sure we have all started a new web project and then needed to add authentication at a later point. This post is going to cover this process use the Identity Scaffolding feature available in Visual Studio.
Sample
For this example, I’m starting with a new web app created using the following command.
dotnet new webapp
If you have any of the .NET Core 3 previews installed I recommend adding a global.json file in the directory where the application is to be created before running the application creation. I had some issues with the scaffolding in the current preview. The following is the contents of my global.json for an example.
{
"sdk": {
"version": "2.2.104"
}
}
Scaffolding
In Visual Studio right-click on the project and select Add > New Scaffolded Item.
On the Add Scaffold dialog in the left list select Identity in the middle area we want the Identity item and then click the Add button.
Next, on the Add Identity dialog, you get a chance to pick which parts of the provided identity you want to override. I’m going to take the default for all the values. The one exception is the Data context class which I’m using the plus button to the right of the field to add a new one since this project doesn’t currently have any data access in it. When done click the Add button.
After a minute or so identity generation will be complete and a text file will so with some follow up steps. Because of the project type, we started with the only one we need to do anything with is the entity framework migrations. The following are the instructions from the file that will get your database to create/updated with the new data needed to support ASP.NET Core’s Identity.
The generated database code requires Entity Framework Core Migrations. Run the following commands:
1. dotnet ef migrations add CreateIdentitySchema
2. dotnet ef database update
Or from the Visual Studio Package Manager Console:
1. Add-Migration CreateIdentitySchema
2. Update-Database
Finally, in the Pages/Shared directory open the _Layout.cshtml file and add the following to where you want to show the Register and Login links. I added this right after the existing navigation links.
<partial name="_LoginPartial"/>
Wrapping Up
This is a very handle bit of functionality that makes it easy to add Identity for an existing project. You will still be missing some of the nice things provided by creating a project with Identity from the start such as displaying a welcome message with the user’s name, but those bits can be added if it is something you want.
The official docs on this topic cover way more scenarios that this post.
Preview 3 of ASP.NET Core was released on March 6th. This release added the option to include auth when creating an Angular or React application using the templates provided by Microsoft. I can’t convey how happy this feature makes me. As someone that hasn’t done a super deep dive on auth having a good starting point for a new application is very helpful.
Installation
To get the updated version of the templates install the latest version of the .NET Core 3 previews. You can find the installers here.
Project Creation
Using the .NET CLI from a command prompt in the directory you want the project created in run the following command.
dotnet new react --auth Individual
After the project is built you should be able to use the following command to run the application.
dotnet run
Issues with Preview 3
I did the above and it results in the following error.
It seems that there are a few issues with the React template that shipped with Preview 3. To fix the above error open the ApiAuthorizationConstants.js file found in the ClientApp/src/components/api-authorization directory and make the following change.
./src/components/api-authorization/ApiAuthorizationRoutes.js
Module not found: Can’t resolve ‘./components/api-authorization/Login’ in ‘\ClientApp\src\components\api-authorization’
This fix is a bit more involved. I found the workaround in the known issues page provided by Microsoft.
First, delete the ApiAuthorizationRoutes.js file which is in the same directory as the previous fix. Then replace the contents of App.js found in the ClientApp/src directory with the following.
After the above tweaks, everything just worked. I’m sure by preview 4 the experience will be even better. Even with the issues I hit getting a basic new project going I am very excited. Thank you, ASP.NET team, at Microsoft adding auth to these templates is going to be super helpful. Also, note that Angular template also got an auth option (and it seems to be a smoother experience at the moment).
Back in October, I did a post on Entity Framework Core: Logging which covers enabling logging for Entity Framework Core. This post is going to expand on that previous post and show you how to get the parameter values used in the queries in addition to the SQL statements being used.
Review
This post will not be covering how to set up a logger please see this previous post for those details. The following is the kind of information you get in the log based on the previous post.
Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (41ms) [Parameters=[@__id_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30']
SELECT TOP(2) [m].[Id], [m].[Address], [m].[City], [m].[Email], [m].[Name], [m].[Phone], [m].[PostalCode], [m].[State]
FROM [Contact] AS [m]
WHERE [m].[Id] = @__id_0
This is helpful when you need to verify the queries Entity Framework is producing, but if you are trying to track down a data related problem not knowing what parameters values are being used can be a pain.
Enable Parameter Values in Logging
Entity Framework Core provides an option to enable sensitive data logging. To enable this option open the Startup class and in the ConfigureServices function make the following change to the AddDbContext call for the DbContext you want the option on for.
Since ASP.NET Core 2.2 was released I have been working on getting all my different applications updated and using in-process hosting. I pretty quickly hit an issue with an application that uses SQLite. As soon as the application tried to access the database I ended up with the following error.
SqliteException: SQLite Error 14: ‘unable to open database file’. Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(int rc, sqlite3 db) Microsoft.Data.Sqlite.SqliteConnection.Open() Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnection(bool errorsExpected)
Issue
After some Googling, I found an issue on GitHub that details the problem. It turns out that when the application gets its current directory it is returning the path to the IIS process that is hosting the application instead of the directory when the application is.
Work Around
On another GitHub issue, I found a link to a recommended workaround. Add the following class somewhere in your application. This code comes here.
internal class CurrentDirectoryHelpers
{
internal const string AspNetCoreModuleDll = "aspnetcorev2_inprocess.dll";
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern IntPtr GetModuleHandle(string lpModuleName);
[System.Runtime.InteropServices.DllImport(AspNetCoreModuleDll)]
private static extern int http_get_application_properties(ref IISConfigurationData iiConfigData);
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
private struct IISConfigurationData
{
public IntPtr pNativeApplication;
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.BStr)]
public string pwzFullApplicationPath;
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.BStr)]
public string pwzVirtualApplicationPath;
public bool fWindowsAuthEnabled;
public bool fBasicAuthEnabled;
public bool fAnonymousAuthEnable;
}
public static void SetCurrentDirectory()
{
try
{
// Check if physical path was provided by ANCM
var sitePhysicalPath = Environment.GetEnvironmentVariable("ASPNETCORE_IIS_PHYSICAL_PATH");
if (string.IsNullOrEmpty(sitePhysicalPath))
{
// Skip if not running ANCM InProcess
if (GetModuleHandle(AspNetCoreModuleDll) == IntPtr.Zero)
{
return;
}
IISConfigurationData configurationData = default(IISConfigurationData);
if (http_get_application_properties(ref configurationData) != 0)
{
return;
}
sitePhysicalPath = configurationData.pwzFullApplicationPath;
}
Environment.CurrentDirectory = sitePhysicalPath;
}
catch
{
// ignore
}
}
}
Finally, in the Main function of the Program class add the following line as the first thing in the function.
CurrentDirectoryHelpers.SetCurrentDirectory();
Wrapping Up
With the above changes, all will work as expected. It is my understanding that this issue will be addressed at some point in the future as a patch so this should just be a temporary fix.
My post a few weeks ago on Entity Framework Core: String Filter Tips may have come across as too harsh on client-side evaluation based on what I saw on Reddit. My point wasn’t that you shouldn’t use client-side evaluation when you need too, but that you should be making a choice when to use client-side evaluation and it is very easy to miss when a query is running client-side.
TimeRemove did a great job explaining ways to detect and deal with client-side evaluation which this post will review. The sample application is the same one used in  Entity Framework Core: String Filter Tips as defined in the Sample Application section.
Sample Client-side Query
The following is the query we will be using to trigger client-side evaluation.
Running this query with no change to the application will actually give you the following warning in the Debug Window.
Microsoft.EntityFrameworkCore.Query:Warning: The LINQ expression ‘where (Compare([c].FirstName, “D”, Ordinal) > 0)’ could not be translated and will be evaluated locally.
I’m not sure how long this warning has been there, but this is the first time I have noticed it. Good reminder to make sure and check the debug window more often.
Throw Exception for Client-side Evaluation
Making the following change to the DbContext will cause Entity Framework Core to throw an exception when it does client-side evaluation instead of just showing a warning. In this example, we are overriding the OnConfiguring function of our DbContext and changing to throw an exception if the application is built in debug mode.
Now running the sample query results in the following exception.
InvalidOperationException: Error generated for warning ‘Microsoft.EntityFrameworkCore.Query.QueryClientEvaluationWarning: The LINQ expression ‘where (Compare([c].FirstName, “D”, Ordinal) > 0)’ could not be translated and will be evaluated locally.’. This exception can be suppressed or logged by passing event ID ‘RelationalEventId.QueryClientEvaluationWarning’ to the ‘ConfigureWarnings’ method in ‘DbContext.OnConfiguring’ or ‘AddDbContext’.
There are times when a client-side evaluation is what you want. How do you deal with that need and leave the exception enabled so you get a notification when a client-side evaluation is happening? To accomplish this you will need to split your query into multiple parts running the server evaluated parts and then in a different statement running the client evaluated parts. The following is our sample query broken up so that no exception is thrown.
If I introduced any confusion I hope this post helps clear it up. Just to be 100% clear client-side evaluation isn’t bad, but I feel it is important for it to be a choice that the developer has made. I hope the above will give you the tools to be clear on when you are choosing client-side evaluation.
Thanks again to TimeRemove for the clarifications to my original post.