مطالب
اتصال به بانک اراکل بدون نیاز به نصب oracleclient و یا استفاده از کنترلهای Devart
گام اول: دانلود پکیج odp.net از وبسایت اراکل(Free).
گام دوم: فایلهای
 
size  filename 
 922kb  oci.dll
 1,386kb  Oracle.DataAccess.dll
 1,256kb  orannzsbb11.dll
 127,196kb  oraociei11.dll
 344kb  OraOps11w.dll
در کنار app کپی کنید 
گام سوم: ایجاد connectionstring به صورت زیر:
 Dim oradb As String = "Data Source=(DESCRIPTION=(ADDRESS_LIST=" _
                  + "(ADDRESS=(PROTOCOL=TCP)(HOST=YourServer)(PORT=YourPort)))" _
                  + "(CONNECT_DATA=(SERVER=DEDICATED)(SID=ORCL)));" _
                  + "User Id=UserName;Password=Password;"
        Dim conn As New OracleConnection(oradb)
        Try
            conn.Open()
        Catch ex As Exception
            Throw
        End Try
موفق باشید
پاسخ به بازخورد‌های پروژه‌ها
نحوه سفارشی سازی ویو های این پروژه
با سلام مجدد 
من هنوز مشکل در سفارشی سازی ویوهای این پروژه رو دارم با این مقاله
و نکته زیر 
-اگر تغییری در فایل‌های View، در تعداد و نام آن‌ها صورت گرفت، روی فایل T4MVC.tt کلیک راست کرده و گزینه‌ی اجرای آن‌را انتخاب کنید. پس از این‌کار، مجددا کامپایل پروژه را فراموش نکنید. 
وقتی راست روی T4MVC.tt راست کلیک و run custom tool را می‌زنم اخطار زیر را دریافت می‌کنم 
[Security Warning]
 
Running this text template can potentially harm your computer. Do not run it if you
obtain if rtom an untrusted source.
 
Click OK. to run the template.
Click Cancel top stop the process.
 
[X] Do not show this message again
 
[OK]  [Cancel]
و با زدن ok کلی خطا میده . لطفا راهنمایی بفرمایید.
پاسخ به بازخورد‌های پروژه‌ها
چند دیتا سورس به عنوان ورودی داده
خیلی خیلی ممنونم  از توضیحات شما
البته من در اس کیو ال عمل Pivot  رو انجام میدادم که با توضیحات شما اون رو به این روش تغییر دادم
الان من وقتی این کار رو انجام میدم دیباگ که میکنم دیتا مورد نظر من ایجاد میشه اما این خطا به من داده میشه
Source should be the result of the CrosstabExtension.Pivot method here 
و کد به این صورت نوشته شده است :
 .MainTableDataSource(dataSource =>
                                  {
                                      var crossTabList = Evaluations_Result.Pivot(x => new
                                      {
                                          گروه_سوال = x.QuestionGroupName,
                                          سوال = x.QuestionName,
                                          وزن = x.QuestionWeight.Value
                                      },
                                          x1 => x1.IndexName,
                                          x2 => x2.Count(x => x.IndexName != null));
                                      dataSource.Crosstab(crossTabList);                                    
                                  })
                                  .MainTableAdHocColumnsConventions(adHocColumnsConventions =>
                                  {
                                      adHocColumnsConventions.ShowRowNumberColumn(true);
                                      adHocColumnsConventions.RowNumberColumnCaption("ردیف");
                                  })
                                  .MainTableSummarySettings(summarySettings =>
                                  {
                                      summarySettings.OverallSummarySettings("جمع کل");
                                      summarySettings.PageSummarySettings("جمع صفحه");
                                  })
                                  .MainTableEvents(events =>
                                  {
                                      events.DataSourceIsEmpty(message: "اطلاعاتی برای نمایش وجود ندارد.");
}
و  Evaluations_Result پاسخ یک StoreProcedure است که از سمت دیتابیس میاد
مطالب
شروع به کار با EF Core 1.0 - قسمت 8 - بررسی رابطه‌ی Many-to-Many
در مطلب «بررسی تفصیلی رابطه Many-to-Many در EF Code first» نحوه‌ی مدلسازی رابطه‌ی چند به چند را در EF 6.x بررسی کردیم. یک چنین رابطه‌ای که به همراه مدیریت خودکار join table آن است (جدول BlogPostsJoinTags در شکل زیر)، در EF Core 1.0 RTM پشتیبانی نمی‌شود.


البته همیشه درخواست کنترل این جدول واسط که کاملا از دیدگاه ORMها (تمام آن‌ها) مخفی است، وجود داشته‌است و قرار است این پشتیبانی توسط مفهوم ویژه‌ای به نام shadow properties به نگارش‌های بعدی EF Core اضافه شود.
اما فعلا در نگارش اول آن، توصیه شده‌است که رابطه‌ی many-to-many را به صورت دو رابطه‌ی one-to-many مدلسازی کنید که در ادامه آن‌را بررسی خواهیم کرد. بنابراین پیشنیاز آن مطالعه‌ی مطلب «شروع به کار با EF Core 1.0 - قسمت 7 - بررسی رابطه‌ی One-to-Many» می‌باشد.


مدلسازی موجودیت‌های یک رابطه‌ی چند به چند در EF Core 1.0 RTM توسط Fluent API

در اینجا نحوه‌ی مدلسازی یک رابطه‌ی چند به چند را توسط دو رابطه‌ی one-to-many مشاهده می‌کنید. تنها تفاوت آن با EF 6.x، قید صریح جدول واسط BlogPostsJoinTags است که یک چنین جدولی در EF 6.x به صورت خودکار تشکیل شده و مدیریت می‌شود و کاملا از دید برنامه مخفی است. اما در اینجا (در نگارش اول EF Core) نیاز است این جدول واسط را از حالت مخفی خارج کرد و سپس دو رابطه‌ی یک به چند را به جداول مطالب و تگ‌های آن‌ها تشکیل داد.
مزیت این حالت، دسترسی کامل به طراحی جدول واسط، توسط برنامه است. بنابراین اگر به هر دلیلی نیاز به افزودن خواص بیشتری به این جدول ویژه دارید، اکنون امکان آن میسر است.
    public class Tags
    {
        public Tags()
        {
            BlogPostsJoinTags = new HashSet<BlogPostsJoinTags>();
        }

        public int Id { get; set; }
        public string Name { get; set; }

        public virtual ICollection<BlogPostsJoinTags> BlogPostsJoinTags { get; set; }
    }

    public class BlogPostsJoinTags
    {
        public virtual BlogPosts BlogPost { get; set; }
        public int BlogPostId { get; set; }

        public virtual Tags Tag { get; set; }
        public int TagId { get; set; }
    }

    public class BlogPosts
    {
        public BlogPosts()
        {
            BlogPostsJoinTags = new HashSet<BlogPostsJoinTags>();
        }

        public int Id { get; set; }
        public string Title { get; set; }
        public string Body { get; set; }

        public virtual ICollection<BlogPostsJoinTags> BlogPostsJoinTags { get; set; }
    }
پس از آن باید Context برنامه را نیز جهت ذکر صریح رابطه‌ی یک به چند، ویرایش کرد. با متدهای HasOne و WithMany در مطلب قبل «شروع به کار با EF Core 1.0 - قسمت 7 - بررسی رابطه‌ی One-to-Many» آشنا شدیم و علت نیاز به ذکر صریح آن‌ها، وجود بیش از یک سر رابطه در جدول واسط BlogPostsJoinTags است. در این حالت یافتن InversePropertyها توسط EF Core میسر نیست و حتما باید از یک طرف شروع و سمت دیگر را مشخص کرد.
به علاوه در اینجا تعریف یک composite key را هم بر روی خواص کلید خارجی جدول واسط مشاهده می‌کنید. وجود این کلید ترکیبی سبب خواهد شد که ملزم به ثبت هر دو Id (کلیدهای جداول مطلب و تگ) در حین ثبت در این جدول شویم (یا قید اجباری هر دو طرف رابطه).
    public class MyDBDataContext : DbContext
    {
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(@"Data Source=(local);Initial Catalog=testdb2;Integrated Security = true");
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<BlogPosts>(entity =>
            {
                entity.Property(e => e.Title)
                    .IsRequired()
                    .HasMaxLength(450);
            });

            modelBuilder.Entity<Tags>(entity =>
            {
                entity.Property(e => e.Name)
                    .IsRequired()
                    .HasMaxLength(450);
            });

            modelBuilder.Entity<BlogPostsJoinTags>(entity =>
            {
                entity.HasKey(e => new { e.TagId, e.BlogPostId })
                    .HasName("PK_dbo.BlogPostsJoinTags");

                entity.HasIndex(e => e.BlogPostId)
                    .HasName("IX_BlogPostId");

                entity.HasIndex(e => e.TagId)
                    .HasName("IX_TagId");

                entity.HasOne(d => d.BlogPost)
                    .WithMany(p => p.BlogPostsJoinTags)
                    .HasForeignKey(d => d.BlogPostId)
                    .HasConstraintName("FK_dbo.BlogPostsJoinTags_dbo.BlogPosts_BlogPostId");

                entity.HasOne(d => d.Tag)
                    .WithMany(p => p.BlogPostsJoinTags)
                    .HasForeignKey(d => d.TagId)
                    .HasConstraintName("FK_dbo.BlogPostsJoinTags_dbo.Tags_TagId");
            });
        }

        public virtual DbSet<BlogPosts> BlogPosts { get; set; }
        public virtual DbSet<BlogPostsJoinTags> BlogPostsJoinTags { get; set; }
        public virtual DbSet<Tags> Tags { get; set; }
    }


مدلسازی موجودیت‌های یک رابطه‌ی چند به چند در EF Core 1.0 RTM توسط Data Annotations

در حالت مدلسازی توسط ویژگی‌ها، ذکر InversePropertyها و همچنین ForeignKeyها مقداری واضح‌تر به نظر می‌رسند. به علاوه، یک سری از تنظیمات هم معادل data annotations ایی ندارند؛ مانند composite key تعریف شده‌ی بر روی خواص جدول واسط و همچنین ایندکس‌های تعریف شده، که حتما باید توسط Fluent API تنظیم شوند.
    public class Tags
    {
        public Tags()
        {
            BlogPostsJoinTags = new HashSet<BlogPostsJoinTags>();
        }

        public int Id { get; set; }

        [Required]
        [MaxLength(450)]
        public string Name { get; set; }

        [InverseProperty("Tag")]
        public virtual ICollection<BlogPostsJoinTags> BlogPostsJoinTags { get; set; }
    }

    public class BlogPostsJoinTags
    {
        [ForeignKey("BlogPostId")]
        [InverseProperty("BlogPostsJoinTags")]
        public virtual BlogPosts BlogPost { get; set; }
        public int BlogPostId { get; set; }

        [ForeignKey("TagId")]
        [InverseProperty("BlogPostsJoinTags")]
        public virtual Tags Tag { get; set; }
        public int TagId { get; set; }
    }

    public class BlogPosts
    {
        public BlogPosts()
        {
            BlogPostsJoinTags = new HashSet<BlogPostsJoinTags>();
        }

        public int Id { get; set; }

        [Required]
        [MaxLength(450)]
        public string Title { get; set; }

        public string Body { get; set; }

        [InverseProperty("BlogPost")]
        public virtual ICollection<BlogPostsJoinTags> BlogPostsJoinTags { get; set; }
    }

    public class MyDBDataContext : DbContext
    {
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(@"Data Source=(local);Initial Catalog=testdb2;Integrated Security = true");
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<BlogPostsJoinTags>(entity =>
            {
                entity.HasKey(e => new { e.TagId, e.BlogPostId })
                    .HasName("PK_dbo.BlogPostsJoinTags");

                entity.HasIndex(e => e.BlogPostId)
                    .HasName("IX_BlogPostId");

                entity.HasIndex(e => e.TagId)
                    .HasName("IX_TagId");
            });
        }

        public virtual DbSet<BlogPosts> BlogPosts { get; set; }
        public virtual DbSet<BlogPostsJoinTags> BlogPostsJoinTags { get; set; }
        public virtual DbSet<Tags> Tags { get; set; }
    }
همانطور که در مطلب «شروع به کار با EF Core 1.0 - قسمت 6 - تعیین نوع‌های داده و ویژگی‌های آن‌ها» نیز عنوان شد، علت تنظیم MaxLength به عدد 450 این است که بتوان بر روی این ستون ایندکس ایجاد کرد.


نحوه‌ی ثبت اطلاعات در دو رابطه‌ی یک به چند به همراه جدول واسط

در EF 6.x، کار مقدار دهی Idهای جدول واسط به صورت خودکار انجام می‌شود. در اینجا این مقدار دهی را باید به صورت صریح انجام داد:
 var post = new BlogPosts { ... };
context.BlogPosts.Add(post);

var tag = new Tags { ... };
context.Tags.Add(tag);

var postTag = new BlogPostsJoinTags { Tag = tag, BlogPost = post };
context.PostsTags.Add(postTag);

context.SaveChanges();


نحوه‌ی واکشی اطلاعات به هم مرتبط در دو رابطه‌ی یک به چند به همراه جدول واسط

در مورد متدهای Include و ThenInclude در مطلب «شروع به کار با EF Core 1.0 - قسمت 7 - بررسی رابطه‌ی One-to-Many» پیشتر بحث شد.
            BlogPosts post1 = this.BlogPosts
                  .Include(blogPosts => blogPosts.BlogPostsJoinTags)
                    .ThenInclude(joinTags => joinTags.Tag)
                  .First(blogPosts => blogPosts.Id == 1);
            IEnumerable<Tags> post1Tags = post1.BlogPostsJoinTags.Select(x => x.Tag);
در اینجا اگر می‌خواهیم به لیست تمام برچسب‌های اولین مطلب دسترسی پیدا کنیم، ابتدا باید رابطه‌ی جدول واسط را Include کنیم. سپس چون در همین سطح می‌خواهیم به سطح بعدی تگ‌های مرتبط برسیم، باید از متد الحاقی جدید ThenInclude استفاده کرد. در غیراینصورت در سطر بعدی، post1.BlogPostsJoinTags نال خواهد بود و همچنین حاوی لیست تگ‌ها نیز نخواهد بود.


یک نکته‌ی تکمیلی
وضعیت پشتیبانی از رابطه‌ی many-to-many را همانند EF 6.x در EF Core، در اینجا می‌توانید پیگیری کنید.
نظرات مطالب
طراحی گردش کاری با استفاده از State machines - قسمت اول
با توجه به اینکه اطلاعات مربوط به State ها، همینطور Transition‌ها و ... در بانک اطلاعاتی ذخیره می‌شود  برای به گردش درآوردن باید با fetch کردن داده‌ها از بانک اطلاعات یک Object را به گردش درآوریم. حال برای ساختن و کانفیگ کلاس مربوط به State Machine به نظر می‌رسد یک راه این باشد: 
 
private StateMachine<string, string> stateMachine;
        private StateMachineCOM source;
        private string startState;
        public delegate void UnhandledTriggerDelegate(State state,  StateConfig trigger);
        public delegate void EntryExitDelegate();
        public delegate bool GuardClauseDelegate();
        public string Id;
        public EntryExitDelegate OnEntry = null;
        public EntryExitDelegate OnExit = null;
        public GuardClauseDelegate GuardClauseFromToTrigger = null;
        public UnhandledTriggerDelegate OnUnhandledTrigger = null;

        public StateMachineRequest(StateMachineCOM source, string startStateId)
        {
            this.source = source;   
            this.startState = startStateId;
        }

        public void Configure() 
        {
            this.stateMachine = new StateMachine<string, string>(startState);
            var states = source.States;
            states.ForEach(state =>
            {
                var triggers = source.StateConfigs.AsQueryable()
                                   .Where(config => config.FromStateId == state.StateId)
                                   .Select(config => new {Id=config.TransitionId.ToString(), From= config.FromStateId.ToString(), To= config.ToStateId.ToString(), Permit=config.PermiteAction })
                                   .ToList();

                triggers.ForEach(trig =>
                {
                    this.stateMachine.Configure(state.StateId.ToString())
                });
            });
        }

        public bool TryFireTrigger(string TrigerId)
        {
            if (!stateMachine.CanFire(TrigerId))
            {
                return false;
            }
            stateMachine.Fire(TrigerId);
            return true;
        }
        
        public string GetCurrentState()
        {
            return this.stateMachine.State;
        }

باشد یعنی State‌ها Transition‌ها و ... را بعد از Fetch کردن از بانک اطلاعاتی به State Machine ارسال کنیم. حالا برای در نظر گرفتن شروط مربوط به OnEntry و OnExit یا GuardClauseFromToTrigger پیشنهاد شما توجه به اینکه براساس State می‌بایست این متدها ساخته شوند چیست؟
- آیا بهتر است delegate پارامتر دریافت کند؟
اگر بله پیاده سازی آن در هنگام کانفیگ به چه صورت است؟ به این صورت ؟
this.stateMachine.Configure(state.StateId.ToString())
                        .OnEntry(() => { if (state.OnEnter) OnEntry(trig.Id);})
                        .OnExit(() => { if (state.OnExit) OnExit(trig.Id); })
                        .PermitIf(trig.From, trig.To, () => { if (trig.Permit) return GuardClauseFromToTrigger(); return true; });
- اگر خیر چگونه می‌توان این متدها را بصورت دینامیک ایجاد کرد و به هنگام کانفیگ ماشین حالت به آن انتساب داد و بعد در هنگام گردش آبجکت به آن دسترسی داشت؟
مطالب
خواندن سریع اطلاعات فایل اکسل و ذخیره در بانک SQL
یکی از زمانبرترین عملیاتها در نرم افزار‌های اتوماسیون، خواندن اطلاعات از فایل‌های اکسل با حجم بالا است. در صورتی که این کار را می‌توان با استفاده از کلاس SqlBulkCopy  به سرعت انجام داد. در ادامه نحوه استفاده از این کلاس، همراه نمونه کدها آورده شده است.
توضیحات به صورت Comment است.
            try
            {
//انتخاب فایل اکسل
                OpenFileDialog ofd = new OpenFileDialog();
                ofd.Title = "انتخاب فایل اکسل حاوی اطلاعات";
                ofd.Filter = "فایل اکسل 2003 (*.xls)|*.xls|فایل اکسل 2007 به بعد(*.xlsx)|*.xlsx";
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    string excelConnectionString = "";
                    string SourceFilePath = ofd.FileName;
//ایجاد کانکشن استرینگ برا خواندن کل اطلاعات از فایل اکسل و ریختن آنها در یک دیتاتیبل به نام dt
                    if (System.IO.Path.GetExtension(ofd.FileName) == ".xlsx")
//تشخیص نوع فایل اکسل برای ایجاد کانکشن استرینگ برای نسخه‌های مختلف اکسل
                        excelConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + SourceFilePath + ";Extended Properties=Excel 12.0";
                    else if (System.IO.Path.GetExtension(ofd.FileName) == ".xls")
                        excelConnectionString = "Provider=Microsoft.Jet.Oledb.4.0;Data Source=" + SourceFilePath + ";Extended Properties=Excel 8.0";

                    DataTable dt = new DataTable("tblinfos");


                    using (System.Data.OleDb.OleDbConnection connection = new System.Data.OleDb.OleDbConnection(excelConnectionString))
                    {
                       
                        connection.Open();

                        System.Data.OleDb.OleDbDataAdapter da = new System.Data.OleDb.OleDbDataAdapter("SELECT * FROM [List$]", connection);//List نام شیت در فایل اکسل است

                        da.Fill(dt);
                        connection.Close();

                    }

                    using (System.Data.OleDb.OleDbConnection connection = new System.Data.OleDb.OleDbConnection(excelConnectionString))
                    {
                        this.Cursor = Cursors.WaitCursor;

                        connection.Open();
//ایجاد ارتباط با بانک اس کیو ال
                        string sqlConnectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\BankDPR.mdf;Max Pool Size=6000; Connection Timeout=50;Integrated Security=True;User Instance=True";
                        

                        Dataaccess db = new Dataaccess();
                        DataTable dtr = db.select("Select Top(1) * From tblinfos");//بدست آورن نام ستون‌های جدول مورد نظر برای تطبیق با ستونهای فایل اکسل
                        //*******************   Fast Copy
                        using (System.Data.SqlClient.SqlBulkCopy bulkCopy = new System.Data.SqlClient.SqlBulkCopy(sqlConnectionString, System.Data.SqlClient.SqlBulkCopyOptions.KeepIdentity))//تعریف یک شی از کلاس SqlBulkCopy 
                        {
                            for (int i = 1; i < dtr.Columns.Count; i++)
                            {
                                bulkCopy.ColumnMappings.Add(dt.Columns[i - 1].Caption, dtr.Columns[i].Caption);//با استفاده از خاصیت ColumnMappings نام ستونهای فایل اکسل با نام ستونهای جدول مورد نظر بانک sql تطبیق داده می‌شود
                            }

                            bulkCopy.DestinationTableName = "tblinfos";//مشخص نمودن نام جدول که قرار است اطلاعات درون ان کپی گردد
                            bulkCopy.WriteToServer(dt);//انجام عملیات کپی اطلاعات از دیتاتیبل با نام dt به بانک

                        }

                        this.Cursor = Cursors.Arrow;
                        MessageBox.Show("اطلاعات از فایل شما خوانده شد");

                    }
                }
            }
            catch (Exception ex)
            {
                this.Cursor = Cursors.Arrow;

                MessageBox.Show(ex.Message, "error");
            }

اشتراک‌ها
بررسی Native AOT در دات‌نت 8
Deep .NET - Ahead of Time Compilation (Native AOT) with Eric Erhardt

Scott Hanselman is joined by Eric Erhardt to go deep on all things Native AOT, that is right, Ahead of Time Compilation. Learn about everything Native AOT from start to finish and how .NET leverages this technology to make your apps and code super fast.

Chapters:
00:00:00 Intro
00:04:17 Understanding the Options and Restrictions of Publishing in .NET Apps
00:06:46 Limitations and Benefits of Native AOT
00:12:33 Development and Implementation of Web API AOT
00:16:28 Use of Create Small and Source Generators in Web Development
00:22:03 Role and Impact of Source Generators in Software Development
00:29:17 Application Performance Optimization and Role-Based Optimization in Web Development
00:33:27 Program Optimization Techniques and Trade-offs
00:37:28 Trade-offs and Considerations in Application Optimization
00:41:27 Understanding the Challenges and Limitations of Implementing AOT
00:46:34 Understanding and Implementing AOT
00:52:56 Understanding Model Streaming Extensions
00:55:50 C# 11 and AOT
01:03:49 Understanding and Addressing AOT Compatibility Issues
01:08:54 Understanding Trimming
01:10:35 Understanding and Addressing System Memory Data and Error Handling
01:16:16 Binary Data Compatibility and Source Generation in Visual Studio
01:24:25 Advanced Features
01:25:29 Wrap-up
بررسی Native AOT در دات‌نت 8
نظرات مطالب
Blazor 5x - قسمت دهم - مبانی Blazor - بخش 7 - مسیریابی
تعدادی پرسش و پاسخ تکمیلی مباحث مسیریابی

چگونه می‌توان DateTime را به عنوان پارامتر مسیریابی ارسال کرد؟
Blazor از پارامترهایی از نوع DateTime، در حین مسیریابی پشتیبانی می‌کند؛ با این شرط که قید datetime در حین مسیریابی صریحا ذکر شود:
@page "/route/{parameter:datetime}"
یک مثال: کامپوننت index.razor که سبب هدایت به سمت کامپوننت دیگری به همراه ارسال پارامتری از نوع DateTime می‌شود:
@page "/"
@inject NavigationManager NavManager
<button @onclick="CurrentTime">Current Time</button>
@code {
    public void CurrentTime()
    {
        NavManager.NavigateTo("/time/" + DateTime.Now);
    }
}
و کامپوننت Time.razor که قادر است این DateTime را دریافت کرده و به یک پارامتر، Bind کند:
@page "/time/{param:datetime}"
<h3>Time</h3>
<p>@Param</p>
@code {
    [Parameter]
    public DateTime Param { get; set; }
}


چگونه می‌توان به عنوان صفحه‌ی جاری دسترسی یافت؟
برای اینکار نیاز است از JavaScript interop استفاده کرد. ابتدا برای مثال تابع عمومی getTitle را که بر اساس DOM API مرورگر کار می‌کند، تهیه می‌کنیم:
window.getTitle = () => {
   return document.title;
};
سپس می‌توان از آن در یک کامپوننت Blazor به صورت زیر استفاده کرد:
@page "/"
@inject IJSRuntime jsRuntime
<h2>Page Title: @Title</h2>
<button class="btn btn-primary" @onclick="@GetTitle">Get Title</button>
@code {
public string Title = "";
    
    public async void GetTitle()
    {
            Title = await jsRuntime.InvokeAsync<string>("getTitle");
     }
}

چگونه می‌توان مسیری را از طریق کدهای برنامه در یک برگه‌ی مجزای مرورگر باز کرد؟
در اینجا نیز می‌توان با استفاده از JavaScript interop، متد استاندارد open مرورگر را فراخوانی کرد و پارامتر اول آن‌را به url مدنظر و پارامتر بعدی آن‌را به blank_ تنظیم کرد تا مرورگر آدرس درخواستی را در یک برگه‌ی جدید باز کند:
@inject IJSRuntime jsRuntime

<button @onclick="NavigateToNewTab">New Tab Navigation</button>
@code {
public async Task NavigateToNewTab()
    {
        string url = "/counter";
        await jsRuntime.InvokeAsync<object>("open", url, "_blank");
    }
}
مطالب
شروع به کار با Aurelia
در این مطلب قصد داریم نحوه‌ی راه اندازی و شروع به کار با Aurelia را توضیح دهیم. برای شروع ابتدا باید Git را نصب کنیم. زیرا می‌خواهیم از jspm برای نصب محتویات Aurelia استفاده کنیم و برای کار کردن با jspm باید Git بر روی سیستم نصب باشد. در صورتیکه Git نصب نباشد، زمان init کردن jspm با خطای زیر رو به رو می‌شویم :

پس از نصب Git اطمینان حاصل کنید که NodeJs ، npm و jspm نیز بر روی سیستم شما نصب باشند. در این قسمت گفته‌ایم که چگونه از این «اطمینان» آگاه شوید.

حال نوبت به ساخت اولین پروژه‌ی MVC ما می‌رسد. یک پروژه MVC جدید با نام دلخواه خودتان در مسیر دلخواه خودتان ایجاد کنید. با خط فرمان، در ریشه‌ی پروژه دستور زیر را اجرا کنید:

jspm init

بدون هیچ تغییری، به هیچ کدام از سوالات پاسخ ندهید و از دکمه‌ی enter استفاده کنید تا مقادیر پیشفرض اعمال شوند. اگر تصویر زیر را در خروجی مشاهده کردید یعنی تا بدین جای کار به درستی پیش رفته‌اید :

حالا نوبت به نصب محتویات Aurelia می‌باشد. برای این کار دستورات زیر را اجرا کنید : 

jspm install aurelia-framework
jspm install aurelia-bootstrapper
با صادر کردن دستورات بالا، jspm تمامی فایل‌های مورد نیاز Aurelia را در پوشه‌ی jspm_packages قرار می‌دهد.

توجه داشته باشید، اگر دستورات بالا به درستی اجرا و تکمیل شوند، باید پس از پایان هر دستور، پیام زیر را در انتهای خروجی مشاهده کنید:
 

پس از این کارها، فایل Layout را باز کنید و کدهای آن را به صورت زیر تغییر دهید:
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Aurelia - www.dotnettips.info</title>
</head>
<body aurelia-app>
    <div>
        @RenderBody()
    </div>
    <script src="~/jspm_packages/system.js"></script>
    <script src="~/config.js"></script>
    <script>
        System.import("aurelia-bootstrapper");
    </script>
</body>
</html>
سپس در ریشه‌ی برنامه یک فایل جاوااسکریپت را با نام app ایجاد کنید و کدهای زیر را در آن قرار دهید:
export class App {
    
}
حالا به یک View، برای این کار نیاز داریم. در همان ریشه‌ی سایت یک فایل html را با نام app ایجاد کنید و کدهای زیر را در آن قرار دهید:
<template>
    <h3>www.dotnettips.info</h3>
</template>
پس از سپری کردن این 3 مرحله، برنامه‌ی خود را اجرا کنید. باید خروجی زیر را مشاهده کنید:

در بخش‌های بعدی در مورد کدهای فوق و همچنین به سایر مباحث دیگر Aurelia می‌پردازیم.

نکته‌ی تکمیلی

زمانیکه می‌خواهید از دستوارت jspm استفاده کنید، باید به ریشه‌ی برنامه مراجعه کنید. حال اگر پوشه‌های تودرتوی زیادی داشته باشید، این رفت و آمد‌ها زمانبر و خسته کننده خواهند شد. برای حل این مشکل کافیست روی پروژه، راست کلیک کنید و گزینه‌ی Open Folder in File Explorer را انتخاب کنید تا ریشه‌ی پروژه باز شود. حالا  کافیست در فضای خالی Windows Explorer کلید Shift را گرفته و راست کلیک کنید. حالا یک آیتم جدید با نام Open command window here ظاهر شده است. کافیست روی آن کلیک کنید. CMD در ریشه‌ی سایت باز خواهد شد.


دانلود پروژه جاری در مخزن گیت