I am attempting to read a json file and generate C# code. I have a source generator like below, and if I uncomment the JsonDocument line, the source generator stops working. In fact, if I use any class from System.Text.Json it stops working. I have also attempted to use Newtonsoft.Json same result.
Whilst building the target project that is using this source generator I get a build error error MSB6006: "csc.exe" exited with code -532462766.
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using System.Text.Json;
namespace Raya.Plugin.Registrations.SourceGenerator
{
[Generator]
public class DeviceRegistrationGenerator : ISourceGenerator
{
public void Execute(GeneratorExecutionContext context)
{
var metadata = context.AdditionalFiles.Single(x => x.Path.EndsWith("plugin.metadata.json"));
// var doc = JsonDocument.Parse(metadata.GetText(context.CancellationToken).ToString());
}
public void Initialize(GeneratorInitializationContext context)
{
#if DEBUG
if (!Debugger.IsAttached)
{
Debugger.Launch();
}
#endif
Debug.WriteLine("Initalize code generator");
}
}
}
Generator csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<DevelopmentDependency>true</DevelopmentDependency>
<IncludeBuildOutput>false</IncludeBuildOutput>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<LangVersion>latest</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.4.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.4.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" PrivateAssets="all" />
<PackageReference Include="System.Text.Json" Version="6.0.5" GeneratePathProperty="true" PrivateAssets="all"/>
</ItemGroup>
</Project>
UPDATE
Adding following seems to make it a work a bit, but I am not sure what is happening. Now I am getting InvalidCastException
<PropertyGroup>
<GetTargetPathDependsOn>$(GetTargetPathDependsOn);GetDependencyTargetPaths</GetTargetPathDependsOn>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
</PropertyGroup>
<Target Name="GetDependencyTargetPaths" AfterTargets="ResolvePackageAssets">
<ItemGroup>
<TargetPathWithTargetPlatformMoniker Include="#(ResolvedCompileFileDefinitions)" IncludeRuntimeDependency="false" />
</ItemGroup>
</Target>
Exception
Since the project using this source generator also ends up referencing System.Text.Json.SourceGenerator.dll, I am getting following exception from that dll.
Unhandled Exception: System.InvalidCastException: [A]Microsoft.CodeAnalysis.CSharp.Syntax.CompilationUnitSyntax cannot be cast to [B]Microsoft.CodeAnalysis.CSharp.Syntax.CompilationUnitSyntax. Type A originates from 'Microsoft.CodeAnalysis.CSharp, Version=4.4.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' in the context 'Default' at location 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\Roslyn\Microsoft.CodeAnalysis.CSharp.dll'. Type B originates from 'Microsoft.CodeAnalysis.CSharp, Version=4.4.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' in the context 'LoadFrom' at location 'C:\Users\myuser.nuget\packages\microsoft.codeanalysis.csharp\4.4.0\lib\netstandard2.0\Microsoft.CodeAnalysis.CSharp.dll'
I am new to asp.net core, different languages may have their own dataset migration framework. In asp.net core, how do I migrate my mysql fields to my project? In the past, the fields of the model class were written and mapped to the database. Now, how to map the database to the model class? I found this article, but please tell me how to do it, forgive my question.
https://learn.microsoft.com/en-us/aspnet/core/data/ef-mvc/complex-data-model?view=aspnetcore-6.0
I made a demo of mapping from database to model, you can refer to it.
First, here are the Nuget packages needed:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.22" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.22">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.22">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="MySql.Data.EntityFrameworkCore" Version="8.0.22" />
</ItemGroup>
</Project>
Then enter this command to generate the model file you need.
Scaffold-DbContext "mysql connection" MySql.Data.EntityFrameworkCore -OutputDir Models
You need to fill in your database connection address, and choose which directory you output to. My side is the Models directory.
Creating a Connector/NET Connection String:
https://dev.mysql.com/doc/connector-net/en/connector-net-connections-string.html
Table in mysql:
The final generated file:
public partial class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Pwd { get; set; }
}
You can refer to this article:
https://dev.mysql.com/doc/connector-net/en/connector-net-entityframework-core-scaffold-example.html
I just learn to use ASP.NET CORE 2.0 MVC using Visual Studio Community Edition.
I want to use MySQL database instead of using SQL Server because I need to use some data inside the old MySQL DB. Please help me solving this problem .. thank you
Here is my error:
Severity Code Description Project File Line Suppression State
Error CS1061 'DbContextOptionsBuilder' does not contain a definition
for 'UseMySql' and no extension method 'UseMySql' accepting a first
argument of type 'DbContextOptionsBuilder' could be found (are you
missing a using directive or an assembly
reference?) LearnEFCore d:\temp\aspnet\LearnEFCore\LearnEFCore\Startup.cs 29 Active
My code as follow:
In Startup.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;
using LearnEFCore.Data;
....
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
var sqlConnectionString = Configuration.GetConnectionString("DataAccessMySqlProvider");
services.AddDbContext<SchoolContext>(options => options.UseMySql(sqlConnectionString));
services.AddMvc();
}
In my appsettings.json
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Warning"
}
},
"ConnectionStrings": {
"DataAccessMySqlProvider": "server=localhost;port=3306;userid=root;password=root;database=sportstore;"
}
}
In my Models/Data
using LearnEFCore.Models;
using Microsoft.EntityFrameworkCore;
namespace LearnEFCore.Data
{
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
{
}
public DbSet<Course> Courses { get; set; }
public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Student> Students { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Course>().ToTable("Course");
modelBuilder.Entity<Enrollment>().ToTable("Enrollment");
modelBuilder.Entity<Student>().ToTable("Student");
}
}
}
My csproj
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.0" />
<PackageReference Include="MySql.Data.EntityFrameworkCore" Version="6.10.4" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" />
</ItemGroup>
</Project>
changin to Pomelo.EntityFrameworkCore.MySql solved the problem ...
I'm working at a middleware for aspnetcore2.0 where I want to execute some razor view.
Actually I need a error handling middleware which would show nice pages from razor views. I know that it's possible to do with UseStatusCodePagesWithReExecute based on status codes. But I need a more general approach - handle an exception in my middleware to delegate (in some cases) it to an error view.
I realized that DeveloperExceptionPageMiddleware does something similar to what I need. But I can't understand how it works even after digging into its sources.
Here is the place where that middleware returns a view - https://github.com/aspnet/Diagnostics/blob/dev/src/Microsoft.AspNetCore.Diagnostics/DeveloperExceptionPage/DeveloperExceptionPageMiddleware.cs#L206
But I can't understand what kind of view it is. It's nor a razor page (as it has no #page directive) neither an mvc view (but i'm not sure).
In the project there're two files for that view: ErrorPage.cshtml and ErrorPage.Designer.cs. How that Designer.cs was created? It looks like a generated file. But thanks to it there's a normal class in the project (ErrorPage) which can be used explicitly. It inherits Microsoft.Extensions.RazorViews.BaseView class from Microsoft.Extensions.RazorViews.Sources package.
So the middleware just execute that view:
var errorPage = new ErrorPage(model);
return errorPage.ExecuteAsync(context);
How can it be achieved in my project?
UPDATE [2018.06]: Please note that the post was written for .NET Core 2.0 times, there're breaking changes for RazorEngine in .NET Core 2.1.
It turned out that it's pretty easy to do.
Aspnet prjoect has an internal tool called RazorPageGenerator (see https://github.com/aspnet/Razor/tree/dev/src/RazorPageGenerator) which can be used to compile views. After compilation with this tool we'll get normal classes which can be used in middlewares.
But before we need to get RazorPageGenerator and slightly customize it.
1.Create a new console project
dotnet new console -o MyRazorGenerator
2.put NuGet.config inside this folder
<configuration>
<config>
<add key="globalPackagesFolder" value="./packages" />
</config>
<packageSources>
<add key="aspnetcore-dev" value="https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json " />
</packageSources>
</configuration>
3.Add the following in csprj (as dotnet add package doesn't support installing pre-prelease packages)
<ItemGroup>
<PackageReference Include="RazorPageGenerator" Version="2.1.0-*" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.Extensions" Version="2.1.0-*" />
<PackageReference Include="Microsoft.AspNetCore.Razor.Language" Version="2.1.0-*" />
</ItemGroup>
4.restore dotnet restore to check you got RazorPageGenerator
5.add into Program.cs:
public static int Main(string[] args)
{
if (args == null || args.Length < 1)
{
Console.WriteLine("Invalid argument(s).");
return 1;
}
var rootNamespace = args[0];
var targetProjectDirectory = args.Length > 1 ? args[1] : Directory.GetCurrentDirectory();
var razorEngine = RazorPageGenerator.Program.CreateRazorEngine(rootNamespace, builder => {
FunctionsDirective.Register(builder);
InheritsDirective.Register(builder);
SectionDirective.Register(builder);
});
var results = RazorPageGenerator.Program.MainCore(razorEngine, targetProjectDirectory);
foreach (var result in results)
{
File.WriteAllText(result.FilePath, result.GeneratedCode);
}
Console.WriteLine();
Console.WriteLine($"{results.Count} files successfully generated.");
Console.WriteLine();
return 0;
}
6.Now we have our own generator and can compile views
7.Create a Razor View (.cshtml)
8.run our generator to compile view:
dotnet run --project .\MyRazorPageGenerator\MyRazorPageGenerator.csproj Croc.XFW3.Web .\Middleware
here I assume that the view is inside Middleware\Views folder.
9.Generator creates a file like ErrorPage.Designer.cs (if view was ErrorPage.cshtml) which we can use:
public async Task Invoke(HttpContext context)
{
try
{
await _next.Invoke(context);
if (context.Response.StatusCode == StatusCodes.Status404NotFound)
{
var statusCodeFeature = context.Features.Get<IStatusCodePagesFeature>();
if (statusCodeFeature == null || !statusCodeFeature.Enabled)
{
if (!context.Response.HasStarted)
{
var view = new ErrorPage(new ErrorPageModel());
await view.ExecuteAsync(context);
}
}
}
}
}
Here we're returning our view in case of 404 error and absense of StatusCodePagesMiddleware. Can be useful for embedded UI in libs.
The generated code uses staff which should be added into your project. To get it we need to acquire nuget package Microsoft.Extensions.RazorViews.Sources. Again it’s not on nuget.org so we need to install it from https://dotnet.myget.org/feed/aspnetcore-dev/package/nuget/Microsoft.Extensions.RazorViews.Sources.
I am using the NLog logging framework and am trying to get exception and stacktrace information showing up in any UDP logger appliaction, such as Sentinel and Log2Console, but can only get the log message part displayed. Outputting to a file works well as most examples do just that, so the problem revolves around using network targets with NLog.
Bonus if a custom format can be applied on inner exceptions and stacktrace, but this is not required. Exception.ToString() would go a long way.
Note on the example code: With Log2Console I found an article on how to send exception as a separate log entry. Although this worked, I was not happy with the solution.
Example exception logging code:
Logger Log = LogManager.GetCurrentClassLogger();
try
{
throw new InvalidOperationException("My ex", new FileNotFoundException("My inner ex1", new AccessViolationException("Innermost ex")));
}
catch (Exception e)
{
Log.ErrorException("TEST", e);
}
Example NLog.config:
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets async="true">
<!-- Send by UDP to Sentinel with NLogViewer protocol -->
<target name="network" xsi:type="NLogViewer" address="udp://192.168.1.3:9999" layout="${message}${onexception:inner=${newline}${exception:format=tostring}}" />
<!-- Send message by UDP to Log2Console with Chainsaw protocol -->
<target name="network2" xsi:type="Chainsaw" address="udp://192.168.1.3:9998" appinfo="Grocelist"/>
<!-- Send exception/stacktrace by UDP to Log2Console with generic network protocol -->
<target name="network2ex" xsi:type="Network" address="udp4://192.168.1.3:9998" layout="${exception:format=ToString}" />
<target name="logfile" xsi:type="File" layout="${longdate}|${level:uppercase=true}|${logger}|${message}|${exception:format=tostring}"
createDirs="true"
fileName="${basedir}/logs/${shortdate}.log"
/>
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="logfile" />
<logger name="*" minlevel="Debug" writeTo="network" />
<logger name="*" minlevel="Debug" writeTo="network2" />
<logger name="*" minlevel="Warn" writeTo="network2ex" />
</rules>
</nlog>
Some links:
http://nlog-project.org
http://nlog-project.org/wiki/Targets
http://nlog-project.org/wiki/Exception_layout_renderer
http://nlog-project.org/2011/04/20/exception-logging-enhancements.html
http://nlog-project.org/wiki/How_to_properly_log_exceptions%3F
How to tell NLog to log exceptions?
https://stackoverflow.com/a/9684111/134761
http://nlog-forum.1685105.n2.nabble.com/How-to-send-stacktrace-of-exceptions-to-Chainsaw-or-Log2Console-td5465045.html
Edit:
After searching some more this seems to be a limitation on NLog's end. A recent patch is apparently out there: log4jxmlevent does not render Exception
Edit2:
I rebuilt NLog with patch, but it did not seem to help in Sentinel or Log2Console apps. I might have to try log4net to make sure those apps really do support what I am trying to achieve.
Edit3:
I currently use string.Format() to join and format message and exception text myself. This works well, but is not what I'm looking for here.
You can also extend NLog to include exceptions for network logging.
Create an extended layout:
[Layout("Log4JXmlEventLayoutEx")]
public class Log4JXmlEventLayoutEx : Log4JXmlEventLayout
{
protected override string GetFormattedMessage(LogEventInfo logEvent)
{
string msg = logEvent.Message + " ${exception:format=Message,Type,ToString,StackTrace}";
msg = SimpleLayout.Evaluate(msg, logEvent);
LogEventInfo updatedInfo;
if (msg == logEvent.Message) {
updatedInfo = logEvent;
} else {
updatedInfo = new LogEventInfo(
logEvent.Level, logEvent.LoggerName,
logEvent.FormatProvider, msg,
logEvent.Parameters, logEvent.Exception);
}
return base.GetFormattedMessage(updatedInfo);
}
}
Create a target that uses that layout
[Target("NLogViewerEx")]
public class NLogViewerTargetEx : NLogViewerTarget
{
private readonly Log4JXmlEventLayoutEx layout = new Log4JXmlEventLayoutEx();
public override Layout Layout { get { return layout; } set {} }
}
Update NLog.config:
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<extensions>
<add assembly="Assembly.Name.That.Contains.Extended.Target"/>
</extensions>
<targets>
<target name="logViewer"
xsi:type="NLogViewerEx"
address="udp://localhost:7071">
</targets>
...
</nlog>
A few years later and this is pretty trivial, try adding
includeSourceInfo="true"
to your target file, so it looks like;
<target name="viewer"
xsi:type="NLogViewer"
includeSourceInfo="true"
address="udp://127.0.0.1:9999" />
Gives you Source File, Line, Class and Method info.
I had this problem, and just updated my NLog nuget package to 2.0.1.2
Now I have exceptions coming through to Log2Console just fine.
Have you tried the latest developer snapshot of Chainsaw? It will display stack traces and supports log4net/UDP appenders, and according to NLog you can use it as well:
http://nlog-project.org/wiki/Chainsaw_target
Try the latest developer snapshot, has a ton of features: http://people.apache.org/~sdeboy
Just download and build the latest (NLog-Build-2.0.0.2007-0-g72f6495) sources from GitHub: https://github.com/jkowalski/NLog/tree/
This issue is fixed there by NLog developer.
In your NLog.config modify the target like the following.
<target name="file" xsi:type="File" fileName="log.txt" layout="${longdate}:${message} ${exception:format=message,stacktrace:separator=*}" />
The part that you are looking for is
${exception:format=message,stacktrace:separator=*}
For more information on this look here.