Search This Blog

Showing posts with label Serentiy. Show all posts
Showing posts with label Serentiy. Show all posts

Serenity Using SERGEN generated Grid in a Dialog

Suppose we generated code using SERGEN for 2 tables (Region,Territories) of NorthWind Sample DataBase. DDL Statements of these tables are
		CREATE TABLE region (
region_id smallint NOT NULL PRIMARY KEY,
region_description bpchar NOT NULL
);
CREATE TABLE territories (
territory_id character varying(20) NOT NULL PRIMARY KEY,
territory_description bpchar NOT NULL,
region_id smallint NOT NULL,
FOREIGN KEY (region_id) REFERENCES region
);


Create following function in file TerritoriesGrid.ts

        public set_Filter(value: string): void {
            //We created the QuickFilter on TerritoriesRow.Fields.RegionDescription in 
            //file TerritoriesRow.cs using [QuickFilter] attribute
            //We are just setting that QuickFilter with below statement		
            this.findQuickFilter(Serenity.StringEditor,
                TerritoriesRow.Fields.RegionDescription).value = value;
        }
Add the grid property in RegionDialog.ts file.

	private myGrid: TerritoriesGrid;
Create following function in RegionDialog.ts file.

	protected afterLoadEntity() {
            super.afterLoadEntity();
            $('.s-DialogContent').append('<div id="MyGrid"></div>');
            this.myGrid = new TerritoriesGrid($('#MyGrid'));
            this.myGrid.set_Filter(this.entity.Regiondescription);
            this.myGrid.refresh();
        }
Furthermore, we can remove buttons,toolbars and columns or fields from TerritoriesGrid and RegionDialog as per our requirement.


Serenity Date Input Formatter for Inline Editing in Grids

Inline editing in grids is not recommended in Serenity by its owner. However he demonstrated serenity inline editing in an example with some warnings. There is no date input formatter in this example. We may use the following date input formatter and call this formatter from getColumns function in grid file.

private dateInputFormatter(ctx) {
            var klass = 'edit s-DateEditor';
            var item = ctx.item as StockVerificationDetailRow;
            var pending = this.pendingChanges[item.RecId];
            var column = ctx.column as Slick.Column;

            if (pending && pending[column.field] !== undefined) {
                klass += ' dirty';
            }

            var value;
            if (item[column.field] == null)
                value = item[column.field];
            else
                value = Q.parseDate(item[column.field]).toLocaleDateString();

            return "<input type='text' class='" + klass +
                "' data-field='" + column.field +
                "' value='" + value +
                "' maxlength='" + column.sourceItem.maxLength + "' />" +
                "<script>$('.s-DateEditor').datepicker(); </script>" +
                "<script>$('.s-DateEditor').each(function(){    var value = $(this).val();   var size = value.length;   size = size * 4;       $(this).css('width', size * 3);        });       </script>" +
                "<script>$('.ui-datepicker-trigger').css({'padding-bottom': '4px','height': '24px'}); </script>";
        }
And the following date input inline formatter is working for html 5 datepicker.
private dateInputFormatter(ctx) {
            var klass = 'edit';
            var item = ctx.item as AgentsRow;
            var pending = this.pendingChanges[item.AgentCode];
            var column = ctx.column as Slick.Column;

            if (pending && pending[column.field] !== undefined) {
                klass += ' dirty';
            }

         
            var value;
            if (item[column.field] == null)
                value = item[column.field];
            else
                value = Q.parseDate(item[column.field]).toLocaleDateString();  

            return "<input type='date' class='" + klass +
                "' data-field='" + column.field +
                "' value='" + value +               
                "' maxlength='" + column.sourceItem.maxLength + "'/>";
        }

Create Custom QuickFilter which selects distinct values of same table/view columns

We created a file MyTableClassLookup.cs for custom lookup. And change some fields name according to your requirement.
using ERP.MyModule.Entities;
using Serenity.ComponentModel;
using Serenity.Data;
using Serenity.Web;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
namespace ERP.MyModule
{
[LookupScript("MyModule.CustomLookup", Expiration = -1, Permission = "*")]
public class MyTableClassLookup : RowLookupScript<MyTableClassRow>
{
public MyTableClassLookup()
{
IdField = TextField = "Unit"; //where Unit is property in MyTableClassRow class
}

protected override void PrepareQuery(SqlQuery query)
{
var fld = MyTableClassRow.Fields;


query
.Distinct(true)
.Select(fld.Unit)
.Where(fld.Unit.IsNotNull());

}

protected override void ApplyOrder(SqlQuery query)
{
}

}
}
We add the attribue [LookupEditor(typeof(MyTableClassLookup))] in MyTableClassRow class for property unit.

Serenity Site Navigation Changes

site navigation files

Project_name.Web/Modules/yourModule/yourModuleNavigation.cs
Project_name.Web/Modules/Common/Navigation/NavigationItems.cs.

attribute for navigation

auto generated modules are displayed at the bottom of navigation menu. Navigation items are created with special assembly attributes 

[assembly: NavigationLink(int order, string path, Type controller, string icon = null, string action = "Index")]

e.g.
[assembly: NavigationLink(int.MaxValue, "ERP/Store", typeof(MyPages.StoreController), icon: null)]

first parameter is display order for this navigation item. 


second parameter is navigation title in "Section Title/Link Title" format. We can edit these.

third parameter is type controller, this is linked with our 

[assembly: NavigationMenu(int.MaxValue, "Store/Catalog", icon: "fa-folder-open-o")]

Serentiy Using Grid as an EditorType

Suppose we have 3 tables in DB.
1) Bill (Bill_id, Bill_Number)
2) Item (Item_id, Item_Name)
3) Bill_items (bill_items_id, bill_id,item_id, item_quantity )

and bill_id and item_id are foreign keys in table Bill_items

Generate Code using Sergen for every table in same module i.e. "Store".

Create a file named Modules/Store/BillItems/BillItemsEditor.ts with contents below

/// <reference path="../../Common/Helpers/GridEditorBase.ts" />
  namespace ERP.Store {
@Serenity.Decorators.registerEditor()
export class BillItemsEditor 
  extends Common.GridEditorBase<BillItemsRow> {
protected getColumnsKey() { return "Store.BillItems"; }
protected getDialogType() { return BillItemsEditDialog; } //We are linking our custom dialog here
protected getLocalTextPrefix() { return BillItemsRow.localTextPrefix; }
constructor(container: JQuery) {
super(container);
}

protected getAddButtonCaption() {
return "Add"; // this will rename the "New billItems" button
}
}
}


Note. We cannot bind SERGEN generated dialogs otherwise we will have issues in saving forms etc.

Create a file named Modules/Store/BillItems/BillItemsEditDialog.ts with contents below


/// <reference path="../../Common/Helpers/GridEditorDialog.ts" />
  namespace ERP.Store {
@Serenity.Decorators.registerClass()
export class BillItemsEditDialog extends 
  Common.GridEditorDialog<BillItemsRow> {
protected getFormKey() { return BillItemsForm.formKey; }
//protected getNameProperty() { return BillItemsRow.nameProperty; }
protected getLocalTextPrefix() { return BillItemsRow.localTextPrefix; }
protected form: BillItemsForm;
constructor() {
super();
this.form = new BillItemsForm(this.idPrefix);
}
}
}

Add the following field in BillForm.cs file.
  [BillItemsEditor, IgnoreName]
  public List<Entities.BillItemsRow> ItemList { get; set; }
Also the following in BillRow.cs in class BillRow
        [NotMapped]        
        public System.Collections.Generic.List<Entities.BillItemsRow> ItemList {
            get { return Fields.ItemList[this]; }
            set { Fields.ItemList[this] = value; }
        }

Also the following in BillRow.cs in class RowFields
public ListField<Entities.BillItemsRow> ItemList;

After the above mentioned steps, we will be able to see Grid in Bill Form or dialog.


Remove unnecessay Field i.e. billId from BillItemsForm.cs file. This field will be automatically taken from BillForm.

Remove unnecessay column i.e. BillItemsId,BillNumber from BillItemsColumns.cs file. These fields will not be shown in grid. 

Add the below code in file BillItemsEditor.ts to get values of colmuns 

protected validateEntity(row: BillItemsRow, id: number) {
if (!super.validateEntity(row, id))
return false;


row.ItemName = ItemRow.getLookup()  //edit this 
.itemById[row.ItemId].Name;


return true;
}

Add this attribute in BillRow.cs to ItemList field for save, retrive, update and deleting of records.
[MasterDetailRelation(foreignKey: "BillId", IncludeColumns = "ItemName")]

here the foreignKey, IncludeColumns values must be in billItemsRow.cs file.

We can include multiple columns as below from billItemsRow


[MasterDetailRelation(foreignKey: "BillId", IncludeColumns = "ItemName1,ItemName2")]

Serenity Add New Column in Table and Display in Grid or Dialog



Add column in table manually or by migration. 

Add it in rowFields class at the bottom of classRow.cs
Add it in ClassRow class as a property in classRow.cs and also add [Column("Column_name_in_DB")] attribute.


To display it in grid, add it in classColumns.cs
To display it in dialog, add it in classForm.cs


Note: Newly added column was not a foreign key or primary key.

Add Foreign Key to table and Display it by Mapping(i.e Displaying Corresponding Textual Field)

Serenity entities are more like SQL views. You can bring in fields from other tables with joins.

Add foreign key relation manually or by migration in database. 

Add foreign key field and its corresponding textual field in RowFields class at the bottom of childClassNameRow.cs

Add foreign key field and its corresponding textual field in childClassNameRow class as a property in childClassNameRow.cs

Add following attributes on foreign key field in childClassNameRow class
[ForeignKey("[SCHEMA].[Master_Table_name]", "Column_name")]
[LeftJoin("join_alias_name")]

Add following attributes on corresponding textual field in childClassNameRow class
[Expression("join_alias_name.textual_column_name_in_DB")]


Add textual field in childClassNameColumns.cs file. It will display the mapped text.

Add foreign key field in childClassNameForm.cs file. and add this attribute,
[LookupEditor(typeof(Entities.masterClassNameRow))]
Note: This attribute can be added in childClassNameRow.cs file to foreign key field. 

Add [LookupScript(nameof(masterClassNameRow))] attribute on masterClassNameRow class.

After these 2 recent steps, we will be able to see a dropdown in form.

If you have generated the code via SERGEN (with foreign key relation already
present in database)then you might only need to apply the last step.

Define A New Textual Field Value Inplace


Add Inplace, DialogType parameters in LookupEditor attribute in childClassNameForm.cs file, e.g.

[LookupEditor(typeof(Entities.masterClassNameRow), InplaceAdd = true, DialogType = "ModuleName.masterClassNameDialog")]


Note: This attribute can be added in childClassNameRow.cs file to foreign key field.


Serenity using Enumeration on a Field

Suppose, we want to make a "MovieKind" enum. First we define Enum (separate file is preferred) e.g.

using Serenity.ComponentModel;
using System.ComponentModel;

namespace ERP.MovieDataBase
{
public enum MovieKind
{
[Description("Film")]
Film = 1,
[Description("TV Series")]
TvSeries = 2,
[Description("Mini Series")]
MiniSeries = 3
}
}


In classRow.cs e.g. here we already had a field Kind with property.



       public Int32? Kind

        {
            get { return (Int32?)Fields.Kind[this]; }
            set { Fields.Kind[this] = (Int32?)value; }
        }

We modified it as below,

public MovieKind? Kind

        {
            get { return (MovieKind?)Fields.Kind[this]; }
            set { Fields.Kind[this] = (Int32?)value; }
        }



Serenity Search and Filter Options

Serenity Search Options


A search box is added by default if we auto generate code from SERGEN. This search box can perform search only on first textual field of table. Sergen automatically determines first textual field of a table and adds a [QuickSearch] attribute on it that specifies that text searches should be performed on it.

We can also manually add [QuickSearch] attribute and make these fields searchable. [QuickSearch] attribute can be added on field property in classRow.cs or classColumns.cs files.

We can further customize the search by its paramaters, 

[QuickSearch(SearchType = SearchType.Auto, numericOnly = -1, isExplicit = false)]


We can also add the functionality of allowing user to choose his search field by adding a dropdown on search box. For this we add the following function in classGrid.ts file.


protected getQuickSearchFields() : Serenity.QuickSearchField[] {            
            return [
                { name: "", title: "all" },
                { name: MovieRow.Fields.Description, title: "description" },
                { name: MovieRow.Fields.Storyline, title: "storyline" },
                { name: MovieRow.Fields.Year, title: "year" }
            ];
        }


In the above function, suppose the name of our table is movie and its columns are title, description, storyline and year. And Title "all" will search in every field with [QuickSearch] attribute.



Serenity Filtering Options



To add the filter on field we can use [QuickFilter] attribute. This attribute can be add on fields in classRow.cs or classColumns.cs files. QuickFilter can be a textbox or a dropdown list. 

To make the QuickFilter Dropdowns, the field should be Enum type or a foreign key with [LookupEditor] attribute. Serenity understands these relations, and determines editor type to use by looking at attributes.


Note : In order to enable "Edit Filter" link below every grid, add @Serenity.Decorators.filterable() above the class definition in classGrid.ts file.
   

Customizing Grid(Columns) or Dialog(Form) in Serenity


We have generated forms and grid for movie table here. We will use these in the examples below,


Changing Grid Title

After logging in to the serenity application and navigating to MovieDataBase,  Movie, we will see the following screen. And here we can see the grid title "Movie"



now, open the file movieRow.cs and change the attribute value. This value represents the Grid Title.



Please note that grid title can also be changed from file ClassIndex.cshtml

Changing Form Title

Form title can be changed by changing the [InstanceName(FormTitle)] attribute of class classRow in ClassRow.cs file. This will also change the new button text.

Changing Field Captions in Dialog and Grid

Field caption of both form and grid can be changed from file classRow.cs by changing the attribute [DisplayName("field_name")] of respective field.

Changing Field Captions in dialog

Field caption of dialog(form) can be changed from file classForm.cs by changing the attribute [DisplayName("field_name")] of respective field. This change will overwrite the name in classRow.cs

Changing Field Captions in grid

Field caption of grid can be changed from file classColumns.cs by changing the attribute [DisplayName("field_name")] of respective field. This change will overwrite the name in classRow.cs

Changing Editor Type

Editor is the input element used for the form fields. By default serenity assigns suitable editor for every field depending upon its data type. However we still have some options of changing editor type by using following attributes,
  • DateTimeEditor
  • TextAreaEditor
  • HtmlContentEditor
  • EmailEditor
  • PasswordEditor
  • DateYearEditor
  • ImageUploadEditor
  • MultipleImageUploadEditor

These attributes can be applied to class fields in classRow.cs file. More usage of these attribute can be seen here 

Setting Initial Dialog Size With CSS (Less)

Serene auto generates CSS files. Dialog(form) size can be changed from file at  Project_name.Web\wwwroot\Content\site\site.classdatabase.less by changing the width and height.

.s-ClassDialog {
    > .size { width: 650px; height: 500px; }
    .caption { width: 150px; }

Set Default Value in Form or Grid

Add attribute [DefaultValue("value")]  or [DefaultValue(value)] to the field in classForm.cs file.

remove all buttons from toolbar

remove title from the grid
remove paging functionality
add or remove a column in grid
add or remove a field in dialog
merge two columns in grid

Generate Code from SERGEN (Serenity Code Generator)

After we have created tables in DataBase, we can use SERGEN to generate all the code to make a basic application running i.e. create-update-delete functionality for all those database objects.

Here, we already created a table with the following migration script.

using FluentMigrator;
using System;

namespace ERP.Migrations.DefaultDB
{
    [Migration(20200411033300)]
    public class Class : Migration
    {
        public override void Up()
        {
            this.CreateTableWithId32("Movie", "MovieId", s => s
            .WithColumn("Title").AsString(200).NotNullable()
            .WithColumn("Description").AsString(1000).Nullable()
            .WithColumn("Storyline").AsString(Int32.MaxValue).Nullable()
            .WithColumn("Year").AsInt32().Nullable()
            .WithColumn("ReleaseDate").AsDateTime().Nullable()
            .WithColumn("Runtime").AsInt32().Nullable());
        }
        public override void Down()
        {
        }
    }

}

Login to serenity Application using admin credentials


Now, in the left side navigation pane, goto Administration --> Sergen and select the connection from right pane.


Now select your table i.e Movie and module name i.e. MovieDataBase (Changed from default) in our case. And click the "Generate Code" button.

Now, we can see in solution explorer of visual stdio that SERGEN has generated some files 

We need to build and execute our project using Ctrl+Shift+B. Then after building the project, we get following errors,



To remove these errors, we replaced Stream, StreamField variable types with respective type. In our case these were String, DateTime, StringFeild and DateTimeField in files movieRow.cs, movieForm.cs and movieColumn.cs .

And we added partial keyword to remove the 3rd error.     
public partial class PermissionKeys

Now we will run the project by pressing Ctrl + F5, and after logging in the serenity application, we will navigate to MovieDataBase -->Movie and we can see that here we can add, delete and update data in movie table.



Dot Net Core Migrations for Oracle Database

Suppose,
the name of your project is ERP
the name of your connection is Default

Add a new class file at location ERP.Web/Migrations/DefaultDB, you will get the following code,


using System;                                                           
using System.Collections.Generic;                          
using System.Linq;                                                  
using System.Threading.Tasks;                               
                                                                                 
namespace ERP.Web.Migrations.DefaultDB          
{                                                                               
    public class Class1                                              
    {                                                                           
    }                                                                           
}                                                                               

Edit this code as following

using FluentMigrator;
using System;

namespace ERP.Migrations.DefaultDB

{
    [Migration(1)]
    public class Class1 : Migration
    {
        public override void Up()
        {
        }
        public override void Down()
        {
        }
    }
}

In the above code, [Migration(1)] is the Migration attribute with a unique identifier. 

This identifier is just a value of type int64. Generally using a numbered date format such as yyyyMMdd is a good practice. This number is also for the ordering of migrations. 



note: For Serentiy Migration versions must be in yyyyMMddHHmmss format e.g. [Migration(20200411033300)]

Create Table

using FluentMigrator;
using System;

namespace ERP.Migrations.DefaultDB
{
    [Migration(20200411033300)]
    public class Class1 : Migration
    {
        public override void Up() 
        {
                this.CreateTableWithId32("Movie", "MovieId", s => s
                .WithColumn("Title").AsString(200).NotNullable()
                .WithColumn("Description").AsString(1000).Nullable()
                .WithColumn("Storyline").AsString(Int32.MaxValue).Nullable()
                .WithColumn("Year").AsInt32().Nullable()
                .WithColumn("ReleaseDate").AsDateTime().Nullable());             
        }
        public override void Down()
        {
        }
    }
}

We are creating a table Movie in the above code. MovieId will be its primary key. This will also create a sequence and trigger to auto add the MovieId key.

Note that, while using oracle database, if you have generated Code with SERGEN, you may need to replace stream type with respective types in classRow.cs, classForm.cs and classColumn.cs files.

Add or Delete Table Column

 Alter.Table("Movie")
                .AddColumn("PrimaryImage").AsString(100).Nullable()
                .AddColumn("GalleryImages").AsString(int.MaxValue).Nullable();

Using above code, we can add column to table. To delete a column use the following code.

Delete.Column("PrimaryImage")
                .FromTable("Movie");


Add or Delete Foreign Key

Suppose, we have schema named "movieSchema" and it has two tables Movie and Genre. GenreId is the primary key of Genre table. Movie table also has a column GenreId and it acts as a foreign key. We can add column and define its foreign relationship using following code,

Alter.Table("Movie")
                .AddColumn("GenreId")..AsInt32().NotNullable()
                    .ForeignKey("FK_MovieGenres_GenreId", "movieSchema", "Genre", "GenreId"));
            
We can delete a foreign key as shown in below code,

Delete.ForeignKey("FK_Movie_GenreId")
                .OnTable("Movie");

Directly Execute SQL Query

To execute SQL query directly, use the Execute.Sql function. 

Execute.Sql(
              @"INSERT INTO movieSchema.MovieGenres (MovieId, GenreId) 
                    SELECT m.MovieId, m.GenreId 
                    FROM mov.Movie m 
                    WHERE m.GenreId IS NOT NULL");

Insert Data in Table

We can insert two records in Movie table we created earlier in this post using the following code.

  Insert.IntoTable("Movie").InSchema("movieSchema")
            .Row(new
            {
                Title = "The Matrix",
                Description = "A computer hacker...  its controllers.",
                Storyline = "Thomas A. Anderson ... human rebellion.",
                Year = 1999,
                ReleaseDate = new DateTime(1999, 03, 31),
                Runtime = 136
            })
            .Row(new
            {
                Title = "Fight Club",
                Description = "An insomniac ... much more...",
                Storyline = "A ticking-time-bomb ... oblivion.",
                Year = 1999,
                ReleaseDate = new DateTime(1999, 10, 15),
                Runtime = 139
            });

Configure Serenity with Oracle 19c


  • First establish a development environment to run serenity without oracle. For this install VS 2019, .NET Core 3.1 SDK, NodeJS, Typescript, Serene Template.
  • Then install oracle19c, toad (optional). Also create a schema "mov" using the following code.

CREATE USER MOV
  IDENTIFIED BY "Mov123"
  HTTP DIGEST DISABLE
  DEFAULT TABLESPACE USERS
  TEMPORARY TABLESPACE TEMP
  PROFILE DEFAULT
  ACCOUNT UNLOCK;

-- 6 System Privileges for MOV
GRANT CREATE ANY SYNONYM TO MOV;
GRANT CREATE ANY TABLE TO MOV;
GRANT CREATE ANY TRIGGER TO MOV;
GRANT CREATE SEQUENCE TO MOV;
GRANT CREATE SESSION TO MOV;
GRANT UNLIMITED TABLESPACE TO MOV;



  • Copy modified sergen for orale from below link and place it in d drive

https://drive.google.com/file/d/1tLX7zzBOTKZQa49mZs4npWEcEAySM9ij/view


  • From Visual Stdio, click Tools => NuGet Package Manager => Manage NuGet Packages for Solution
Now, in the browse tab, search "Oracle.ManagedDataAccess.Core" and install it.


  •  add replace this line in file startup.cs

DbProviderFactories.RegisterFactory("Microsoft.Data.Sqlite", Microsoft.Data.Sqlite.SqliteFactory.Instance);

with this line

DbProviderFactories.RegisterFactory("Oracle.ManagedDataAccess.Client",  Oracle.ManagedDataAccess.Client.OracleClientFactory.Instance);

  • Edit connection string in file appsettings.json by replacing the following code,

"Default": {
      "ConnectionString": "Server=(localdb)\\MsSqlLocalDB;Database=Serene7_Default_v1;Integrated Security=true",
      "ProviderName": "System.Data.SqlClient"
    },

with




"Default": { 

"ConnectionString": "User Id=mov;password=Mov123;Data Source=localhost:1521/db19c;",
"ProviderName": "Oracle.ManagedDataAccess.Client"
},



where "mov" is the schema we created in oracle. and db19c is the global database name



  • Edit this file \Project.Web\Modules\Administration\Sergen\SergenEndpoint.cs 

replace the below the below function

private void RunSergen(params string[] arguments)
        {
            var process = Process.Start(new ProcessStartInfo
            {
                FileName = "dotnet",
                CreateNoWindow = true,
                Arguments = "sergen " + string.Join(" ", arguments)
            });

            if (!process.WaitForExit(90000) || process.ExitCode != 0)
                throw new ValidationError("Error while running Sergen!");

        }

with,

private void RunSergen(params string[] arguments)
        {
            var process = Process.Start(new ProcessStartInfo
            {
                FileName = @"D:\sergen\net461\dotnet-sergen.exe",
                CreateNoWindow = true,
                Arguments = string.Join(" ", arguments)
            });

            if (!process.WaitForExit(90000) || process.ExitCode != 0)

                throw new ValidationError("Error while running Sergen!");

        }

and replace the below the below function 
private TOut RunSergen<TOut>(params string[] arguments)
        {
            var tempFile = System.IO.Path.GetTempFileName() + ".json";
            try
            {
                var process = Process.Start(new ProcessStartInfo
                {
                    FileName = "dotnet",
                    CreateNoWindow = true,
                    WorkingDirectory = hostingEnvironment.ContentRootPath,
                    Arguments = "sergen " + string.Join(" ", arguments) + " -o " + Escape(tempFile)
                });

                if (!process.WaitForExit(90000) || process.ExitCode != 0)
                    throw new ValidationError("Error while running Sergen!");

                return JSON.ParseTolerant<TOut>(System.IO.File.ReadAllText(tempFile));
            }
            finally
            {
                System.IO.File.Delete(tempFile);
            }

        }

with,
       
private TOut RunSergen<TOut>(params string[] arguments)
        {
            var tempFile = System.IO.Path.GetTempFileName() + ".json";
            try
            {
                var process = Process.Start(new ProcessStartInfo
                {
                    FileName = @"D:\sergen\net461\dotnet-sergen.exe",
                    CreateNoWindow = true,
                    WorkingDirectory = hostingEnvironment.ContentRootPath,
                    Arguments = string.Join(" ", arguments) + " -o " + Escape(tempFile)
                });
                if (!process.WaitForExit(90000) || process.ExitCode != 0)
                    throw new ValidationError("Error while running Sergen!");
                return JSON.ParseTolerant<TOut>(System.IO.File.ReadAllText(tempFile));
            }
            finally
            {
                System.IO.File.Delete(tempFile);
            }
        }

  • now build and run the solution
Web Statistics