I'm just getting started with biml and bimlscript. I can see the power it holds, but so far digging through the language and API reference has been frustrating. I can't seem to find any reference online to access the package's variable collection.
I'm trying to set up this script so I can add more variables into my Variables section, and then automatically add those variables to a script task later in the process.
Here is the minimal code for my problem:
<Biml xmlns="http://schemas.varigence.com/biml.xsd" >
<Packages>
<Package Name="Load">
<Variables>
<Variable Name="ETLProcessStepID" DataType="Int32">0</Variable>
<Variable Name="TenantID" DataType="Int32">1</Variable>
</Variables>
<!-- more stuff going on in the biml -->
<# var package = RootNode.Packages.Where(loadPackage => loadPackage.Name.Contains("Load"));
foreach (var variable in package.Variables) { #>
<ReadWriteVariables VariableName="<#=variable.Name#>" />
<# }#>
</Package>
</Packages>
</Biml>
This seems to be the closest I've gotten. Unfortunately It results in:
Error 0 'System.Collections.Generic.IEnumerable<Varigence.Languages.Biml.Task.AstPackageNode>' does not contain a definition for 'Variables' and no extension method 'Variables' accepting a first argument of type 'System.Collections.Generic.IEnumerable<Varigence.Languages.Biml.Task.AstPackageNode>' could be found (are you missing a using directive or an assembly reference?).
If I'm reading the documentation right, there is a Variables collection in the Packages node. https://varigence.com/Documentation/Api/Type/AstPackageNode
If I'm not reading the documentation right, can anyone direct me to a reference on how I could access the package variables collection?
The first error you're running into is that your C# variable called package is going to return a collection from that Linq call. Since there should only be one element that matches it, we'll use First to just give us one of these things
var package = RootNode.Packages.Where(loadPackage => loadPackage.Name.Contains("Load")).First();
Now the tricky part and I'll actually have to check with some bigger guns on this, but I don't think you'd be able to access the current package's variable collection like that because it's not built yet. Well, at least using BIDS Helper/BimlExpress. The Biml first needs to get compiled into objects because, assuming a single select, you won't have anything in the RootNode.Packages collection. You certainly wouldn't have "Load" because you're compiling it right now.
In Mist, the paid for solution which is soon to be rebranded as BimlStudio, you could use a Transformer to accomplish this. You'd build out the Load package first and then a transformer fires off just prior to emission as a dtsx package and does whatever correction you were trying.
Consider the following test harness. It creates a simple package and then has some bimlscript immediately after it wherein I enumerate though all the packages and then for each package, I enumerate the root level Variables collection. You'll only see the "Test" message rendered. The inner calls won't fire because nothing exists yet.
<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<Packages>
<Package Name="so_38908470" >
<Variables>
<Variable Name="ETLProcessStepID" DataType="Int32">0</Variable>
<Variable Name="TenantID" DataType="Int32">1</Variable>
</Variables>
<#
string message = "<!-- {0} -->";
WriteLine(message, "test");
foreach (var package in RootNode.Packages)
{
WriteLine(message, package.Name);
foreach(var variable in package.Variables)
{
WriteLine(message, variable.Name);
}
}
#>
</Package>
</Packages>
</Biml>
The more I think about this, Tiering might be able to accomplish this with BIDS Helper/BimlExpress. Since it looks like you're trying to use the Variables defined within a package as inputs to a Script Task or Component, as long as you're using ScriptProjects type things which are parallel to a Packages collection, this might work.
Eureka
Add two Biml files to your project: Load.biml and Script.Biml. Use the following code in each. Select both and right click to generate SSIS package.
Load.biml
This is going to be your package. It is the package you started up above with a Script Task in there that is going to dump the name and value of all the user variables declared at the root of the package. But as you see, there isn't anything in the ScriptTask tag that specifies what variables or what the code is going to do.
<Biml xmlns="http://schemas.varigence.com/biml.xsd" >
<Packages>
<Package Name="Load">
<Variables>
<Variable Name="ETLProcessStepID" DataType="Int32">0</Variable>
<Variable Name="TenantID" DataType="Int32">1</Variable>
</Variables>
<Tasks>
<Script ProjectCoreName="ST_EchoBack" Name="SCR Echo Back">
<ScriptTaskProjectReference ScriptTaskProjectName="ST_EchoBack" />
</Script>
</Tasks>
</Package>
</Packages>
</Biml>
Script.biml
This biml looks like a lot but it's the same concepts as I was working with above where I enumerate though the packages collection and then work with the Variables collection. I use the biml nuggets to control the emission of the Namespace, Name and DataType properties.
<## template language="C#" tier="1" #>
<Biml xmlns="http://schemas.varigence.com/biml.xsd" >
<ScriptProjects>
<ScriptTaskProject ProjectCoreName="ST_EchoBack" Name="ST_EchoBack" VstaMajorVersion="0">
<ReadOnlyVariables>
<!-- List all the variables you are interested in tracking -->
<#
string message = "<!-- {0} -->";
WriteLine(message, "test");
// ValidationReporter.Report(Severity.Error, "test");
foreach (var package in RootNode.Packages.Where(x=> x.Name == "Load"))
{
WriteLine(message, package.Name);
// ValidationReporter.Report(Severity.Error, package.Name);
foreach(var variable in package.Variables)
{
WriteLine(message, variable.Name);
// ValidationReporter.Report(Severity.Error, variable.Name);
#>
<Variable Namespace="<#=variable.Namespace#>" VariableName="<#=variable.Name#>" DataType="<#=variable.DataType#>" />
<#
}
}
#>
</ReadOnlyVariables>
<Files>
<File Path="ScriptMain.cs" BuildAction="Compile">using System;
using System.Data;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;
namespace ST_EchoBack
{
[Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
public void Main()
{
bool fireAgain = false;
string message = "{0}::{1} : {2}";
foreach (var item in Dts.Variables)
{
Dts.Events.FireInformation(0, "SCR Echo Back", string.Format(message, item.Namespace, item.Name, item.Value), string.Empty, 0, ref fireAgain);
}
Dts.TaskResult = (int)ScriptResults.Success;
}
enum ScriptResults
{
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
};
}
} </File>
<File Path="Properties\AssemblyInfo.cs" BuildAction="Compile">
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyVersion("1.0.*")]
</File>
</Files>
<AssemblyReferences>
<AssemblyReference AssemblyPath="System" />
<AssemblyReference AssemblyPath="System.Data" />
<AssemblyReference AssemblyPath="System.Windows.Forms" />
<AssemblyReference AssemblyPath="System.Xml" />
<AssemblyReference AssemblyPath="Microsoft.SqlServer.ManagedDTS.dll" />
<AssemblyReference AssemblyPath="Microsoft.SqlServer.ScriptTask.dll" />
</AssemblyReferences>
</ScriptTaskProject>
</ScriptProjects>
</Biml>
I thought I could simplify call GetBiml() the variable variable but that is going to emit the exact biml it was defined with
<Variable Name="ETLProcessStepID" DataType="Int32">0</Variable>
<Variable Name="TenantID" DataType="Int32">1</Variable>
and if that didn't have the actual value in there, it'd be legit syntax for the ReadOnly/ReadWrite variables collection. Que lástima.
Biml Script Component Source
Biml Test for echo aka Script Task
Related
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 have created a HelperFunctions.cs file containing the following:
using Varigence.Languages.Biml.Table;
public static class HelperFunctions
{
public static string GetDisplayTableName(AstTableNode table)
{
return table.GetTag("DatabaseName").ToUpper() + "_" + table.Schema.Name.ToUpper() + "_" + table.Name.ToUpper();
}
}
However it does not recognise GetTag() and throws the error :
'AstTableNode' does not contain a definition for 'GetTag' and no accessible extension method 'GetTag' accepting a first argument of type 'AstTableNode' could be found (are you missing a using directive or an assembly reference?).
What do I need to add to make this work?
Thanks
Jon
A static method needs to have the parameter prefixed with this
SO_63828312.cs
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Varigence.Biml.Extensions;
using Varigence.Languages.Biml.Table;
public static class HelperFunctions
{
public static string GetDisplayTableName(this AstTableNode table)
{
return table.GetTag("DatabaseName").ToUpper() + "_" + table.Schema.Name.ToUpper() + "_" + table.Name.ToUpper();
}
}
My static Biml defines a table, which needs a schema, which needs a database, which needs a connection. All of that to get us to a table that has an AnnotationType of Tag with a value of AW.
SO_63828312.T0.biml
<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<Connections>
<OleDbConnection ConnectionString="Data Source=localhost\dev2017;Initial Catalog=tempdb;Provider=SQLNCLI11.1;Integrated Security=SSPI;Auto Translate=False;Packet Size=32767;" Name="AdventureWorks" />
</Connections>
<Databases>
<Database Name="AW" ConnectionName="AdventureWorks" />
</Databases>
<Schemas>
<Schema DatabaseName="AW" Name="dbo" />
</Schemas>
<Tables>
<Table Name="foo" SchemaName="AW.dbo">
<Annotations>
<Annotation Tag="DatabaseName" AnnotationType="Tag">AW</Annotation>
</Annotations>
<Columns>
<Column Name="Col1" DataType="Int32"></Column>
</Columns>
</Table>
</Tables>
</Biml>
Tier 1 execution. This begins our dynamic tiering. Since there's only one, I don't explicitly give it one but if you have multiple tiers, you'd want to provide a directive.
Here I enumerate my Tables collection (defined in a preceding tier) and for each table I find, I write the table name and the tag value
SO_63828312.T1.biml
<## code file="SO_63828312.cs" #>
<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<#
string template = "<!-- {0}|{1} -->";
foreach(var t in this.RootNode.Tables)
{
WriteLine(string.Format(template, t.Name, t.GetDisplayTableName()));
}
#>
</Biml>
I am getting the below error when trying to generate a package through BIML using a ScriptTask as a datasource. I have a large (circa 5GB) XML file to load and wanted to use a StreamReader to get the data into the database.
'Output0Buffer' does not contain a definition for 'PORTF_LIST' and no extension method 'PORTF_LIST' accepting a first argument of type 'Output0Buffer' could be found (are you missing a using directive or an assembly reference?).
This is occurring for each column. The columns are dynamic and come from a separate method in a c# class looking at the dacpac so should be the same names and casing everywhere.
Sample of the file as below:
<ANALYTICS>
<INSTRUMENTS ASOF_DATE="3/31/2017" CREATE_DATE="4/2/2017" RECORDS="3763">
<INSTRUMENT>
<PORTF_LIST>XX1245897</PORTF_LIST>
<PRT_FULL_NAME>Convertible Bonds</PRT_FULL_NAME>
<ISIN>11803384</ISIN>
</INSTRUMENT>
</INSTRUMENTS>
</ANALYTICS>
Output buffer is defined as below (there are 250 odd columns, but all follow the same pattern:
<OutputBuffers>
<OutputBuffer Name="Output0" IsSynchronous="false">
<Columns>
<Column Name="PORTF_LIST" DataType="String" Length="255"/>
<Column Name="PRT_FULL_NAME" DataType="String" Length="255"/>
<Column Name="ISIN" DataType="String" Length="255"/>
</Columns>
</OutputBuffer>
</OutputBuffers>
The script task code where I am trying to add to the buffer is below:
<## property name="Elements" type="String" #>
<## property name="Columns" type="String" #>
<## property name="BufferColumns" type="String" #>
<## property name="RootElement" type="String" #>
<ScriptComponentProject ProjectCoreName="SC_eb1debcd2374468ebccbbfad4fbe5976" Name="XmlSource">
<AssemblyReferences>
<AssemblyReference AssemblyPath="Microsoft.SqlServer.DTSPipelineWrap" />
<AssemblyReference AssemblyPath="Microsoft.SqlServer.DTSRuntimeWrap" />
<AssemblyReference AssemblyPath="Microsoft.SqlServer.PipelineHost" />
<AssemblyReference AssemblyPath="Microsoft.SqlServer.TxScript" />
<AssemblyReference AssemblyPath="Microsoft.SqlServer.ManagedDTS.dll" />
<AssemblyReference AssemblyPath="Microsoft.SqlServer.ScriptTask.dll" />
<AssemblyReference AssemblyPath="System.dll" />
<AssemblyReference AssemblyPath="System.AddIn.dll" />
<AssemblyReference AssemblyPath="System.Data.dll" />
<AssemblyReference AssemblyPath="System.Windows.Forms.dll" />
<AssemblyReference AssemblyPath="System.Xml.dll" />
<AssemblyReference AssemblyPath="System.Xml.Linq.dll" />
<AssemblyReference AssemblyPath="System.Core.dll" />
</AssemblyReferences>
<OutputBuffers>
<!--
Define what your buffer is called and what it looks like
Must set IsSynchronous as false. Otherwise it is a transformation
(one row enters, one row leaves) and not a source.
-->
<OutputBuffer Name="Output0" IsSynchronous="false">
<Columns>
<#=BufferColumns#>
</Columns>
</OutputBuffer>
</OutputBuffers>
<Files>
<File Path="Properties\AssemblyInfo.cs">
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyTitle("XmlSource")]
[assembly: AssemblyDescription("Script Component as source")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("XmlSource")]
[assembly: AssemblyCopyright("Copyright # 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("1.0.*")]
</File>
<File Path="main.cs">
<![CDATA[
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using System.Security;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Windows.Forms;
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
public override void PreExecute()
{
base.PreExecute();
}
public override void PostExecute()
{
base.PostExecute();
}
public string sourceFile = Dts.Variables["User::FileName"].Value.ToString();
public override void CreateNewOutputRows()
{
foreach (var myXmlData in (
from elements in StreamReader(sourceFile, "INSTRUMENT")
select new
{
PORTF_LIST = elements.Element("PORTF_LIST").Value,
PRT_FULL_NAME = elements.Element("PRT_FULL_NAME").Value,
ISIN = elements.Element("ISIN").Value
}
))
{
try
{
Output0Buffer.AddRow();
Output0Buffer.PORTF_LIST = myXmlData.PORTF_LIST;
Output0Buffer.PRT_FULL_NAME = myXmlData.PRT_FULL_NAME;
Output0Buffer.ISIN = myXmlData.ISIN;
}
catch (Exception e)
{
string errorMessage = string.Format("Data retrieval failed: {0}", e.Message);
bool cancel;
ComponentMetaData.FireError(0, ComponentMetaData.Name, errorMessage,string.Empty,0, out cancel);
}
}
}
public static IEnumerable<XElement> StreamReader(String filename, string elementName)
{
// Create an XML reader for this file.
using (XmlReader reader = XmlReader.Create(filename))
{
reader.MoveToContent(); // will not advance reader if already on a content node; if successful, ReadState is Interactive
reader.Read(); // this is needed, even with MoveToContent and ReadState.Interactive
while(!reader.EOF && reader.ReadState == ReadState.Interactive)
{
if(reader.NodeType == XmlNodeType.Element && reader.Name.Equals(elementName))
{
// this advances the reader...so it's either XNode.ReadFrom() or reader.Read(), but not both
var matchedElement = XNode.ReadFrom(reader) as XElement;
if(matchedElement != null)
yield return matchedElement;
}
else
reader.Read();
}
reader.Close();
}
}
}
]]>
</File>
</Files>
<ReadOnlyVariables>
<Variable Namespace="User" DataType="String" VariableName="FileName" />
</ReadOnlyVariables>
<ReadWriteVariables>
</ReadWriteVariables>
</ScriptComponentProject>
I've checked the code in a console app and it reads the XML file fine, but no luck with the BIML. There are about 250 odd columns so I am trying to avoid doing this manually so if you have any ideas what I am doing wrong I'd really appreciate it!
It seems that the script task does not like underscores in the OutputBuffer.
I created a stub package manually and intellisense had PORTFLIST rather than PORTF_LIST when assigning the value.
So that snippit of code should be:
Output0Buffer.AddRow();
Output0Buffer.PORTFLIST = myXmlData.PORTF_LIST;
Output0Buffer.PRTFULLNAME = myXmlData.PRT_FULL_NAME;
Output0Buffer.ISIN = myXmlData.ISIN
I have another error, my favorite "EmitSsis. Internal Compiler Error: Workflow EmitSsis contains fatal errors.", but at least this one is solved!
Thanks Bill for your help, and sorry I led you down the garden path with the wrong column name in the posted error, or you probably would have known the issue!
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.
The following xml values is getting from php file
<result>
<list>
<node>air</node>
<node>flex</node>
<node>android</node>
</list>
</result>
i am calling this xml using httpservice
<mx:HTTPService
id="project"
url="http://localhost/eshpm/AIR/newproject.php"
method="POST" result="onResult_projectname(event)" resultFormat="e4x">
<mx:request xmlns="">
<name>yes</name>
</mx:request>
</mx:HTTPService>
The result is obtained using the function
private function onResult_projectname(evt:ResultEvent):void
{
xmldata = new XML(evt.result);
xmlList_user = new XMLListCollection(xmldata.list);
tree.dataProvider = xmlList_user.children();
}
The problem is that i am able to display the values in Tree.......but it is repeating
ie, "air" is comming in tree twice....
plz help.............thanks
Try using <mx:Tree dataProvider="{project.lastResult.result}" labelField="node"/>. By invoking project.send() databinding works and populates your Tree.