I can tell at least that in 3 years, JavaScript will gain more the status of a VM and lose the status of a language. Already today, not many people use raw JavaScript. You usually have some transpilation, at least e.g. Babel. In the future, Web Assembly will enable more innovation in that regards, and existing transpiling languages like Elm, TypeScript, PureScript will continue to improve.
Your software application is like an iceberg. Your users only see a
small fraction of the application, the parts that they interact with.
Your application can be a mess under the covers but as long as you have a
beautiful, quick interface that's super usable, your uses will think
your app is designed really well.
در مورد ادامه ...
- TLS 1.0: The request was aborted: Could not create SSL/TLS secure channel.
- Task List with filter set to Entire Solution doesnt display tasks/todos when the file is closed.
- Fatal error C1001: An internal error has occurred in the compiler.
- VS 2019 Preview 1 - EF6 edmx file cannot be saved.
- vcruntime140.dll should be made available on Microsoft Symbol Server.
- Static Analyser, Custom Rule Set (C++) does not execute included default sets.
- VS2019 Preview: Azure Function publishing does not work.
- References window does not remember its position.
- Missing formatting option for pointers and references.
- Microsoft.TeamFoundation.Client, Version=15.0.0.0 assembly not found when create a new web project.
قسمت قبل به IIS7 اختصاص داشت که شاید برای خیلیها کاربرد نداشته باشد خصوصا اینکه برنامه نویسها ترجیح میدهند به روشهایی روی بیاورند که کمتر نیاز به دخالت مدیر سرور داشته باشد؛ یا زمانیکه سایت شما بر روی یک هاست اینترنتی قرار گرفته است عملا شاید دسترسی خاصی به تنظیمات IIS نداشته باشید (مگر اینکه یک هاست اختصاصی را تهیه کنید).
برای IIS6 و ماقبل از آن و حتی بعد از آن!، حداقل دو روش برای کش کردن اطلاعات استاتیک وجود دارد:
الف) استفاده از web resources معرفی شده در ASP.Net 2.0 به بعد
در مورد نحوهی تعریف و بکارگیری web resources میتوان به مقاله "تبدیل پلاگینهای jQuery به کنترلهای ASP.Net" رجوع کرد.
همانطور که در شکل فوق نیز ملاحظه میکنید، هدر مربوط به مدت زمان منقضی شدن کش سمت کلاینت یک web resource توسط موتور ASP.Net به صورت خودکار به سال 2010 تنظیم شده است و این مقدار خالی نیست.
ب) افزودن این هدر به صورت دستی
برای این منظور باید در نحوهی ارائه فایلهای استاتیک دخالت کنیم و اینکار را با استفاده از یک generic handler میتوان انجام داد.
کد این generic handler میتواند به صورت زیر باشد:
using System;
using System.IO;
using System.Web;
using System.Web.Services;
using System.Reflection;
namespace test1
{
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class cache : IHttpHandler
{
private static void cacheIt(TimeSpan duration)
{
HttpCachePolicy cache = HttpContext.Current.Response.Cache;
FieldInfo maxAgeField = cache.GetType().GetField("_maxAge", BindingFlags.Instance | BindingFlags.NonPublic);
maxAgeField.SetValue(cache, duration);
cache.SetCacheability(HttpCacheability.Public);
cache.SetExpires(DateTime.Now.Add(duration));
cache.SetMaxAge(duration);
cache.AppendCacheExtension("must-revalidate, proxy-revalidate");
}
public void ProcessRequest(HttpContext context)
{
string file = context.Request.QueryString["file"];
if (string.IsNullOrEmpty(file))
{
return;
}
string contetType = context.Request.QueryString["contetType"];
if (string.IsNullOrEmpty(contetType))
{
return;
}
context.Response.Write(File.ReadAllText(context.Server.MapPath(file)));
//Set the content type
context.Response.ContentType = contetType;
// Cache the resource for 30 Days
cacheIt(TimeSpan.FromDays(30));
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
این generic handler دو کوئری استرینگ را دریافت میکند؛ file جهت دریافت نام فایل و contetType جهت مشخص سازی نوع محتوایی که باید سرو شود؛ مثلا جاوا اسکریپت یا استایل شیت و امثال آن. سپس زمانیکه محتوا را Response.Write میکند، هدر مربوط به کش شدن آنرا نیز به 30 روز تنظیم مینماید.
تابع مربوط به کش کردن اطلاعات از مقاله ASP.NET Ajax Under-the-hood Secrets استخراج شد.
روش استفاده در مورد فایلهای CSS
بجای تعریف یک فایل CSS در صفحه، به صورت استاندارد، اکنون تعریف متداول را به صورت زیر اصلاح کنید:
<link type="text/css" href="cache.ashx?v=1&file=site.css&contetType=text/css" rel="Stylesheet" />
روش استفاده در مورد فایلهای JS
<script type="text/javascript" src="cache.ashx?v=1&file=js/jquery-1.3.2.min.js&contetType=application/x-javascript"></script>
ابتدا میخواهیم یک الگو یا Template را درست کنیم و بعدها از روی آن، نامهی جدیدی
را ایجاد کنیم و فیلدهایش را پرکنیم. برای اینکار یک سند جدید را در Word
ایجاد و به سربرگ Mailings مراجعه میکنیم. سپس دکمهی Select Recipients
را بزنید. در ادامه از منوی باز شده، Type a NewList را بزنید. با اینکار پنجرهای باز
میشود. در اینجا دکمهی Customize Columns را بزنید. این پنجره شامل فیلدهایی میشود که
میتوانید از آن استفاده کنید و بر روی سند قرار دهید و داخل برنامه با پیدا کردن
این فیلدها میتوانید بجای آنها، مقدار مورد نظرتان را پاس دهید. حالا شما نیاز
دارید تا از طریق دکمهی Add، تمامی فیلدهای لازم یک نامه را بسازید. پس از این کار، در هر دو پنجره ،
دکمهی OK را بزنید. بدین صورت یک پنجرهی ذخیره برای شما باز میشود تا این فیلدهایی را
که ایجاد کردید، به عنوان یک دیتابیس کوچک ذخیره شود که تمامی فیلدها را
دارا میباشد و هر موقع که خواستید دوباره میتوانید از همین فیلدها استفاده
کنید.
حالا میرسیم به قرار دادن این فیلدها داخل سند. با ذخیره
کردن فیلدها، تمامی گزینههای سربرگ Mailings فعال میشود. شما برای اینکه
فیلدی را بر روی سند قرار دهید، روی Insert Merge Field کلیک و متناسب با نیازتان،
فیلدها را قرار دهید و الگو را طراحی کنید. یک نمونه:
حالا فایل را با پسوند DOT. ذخیره کنید. در ادامه این فایل را در دیتابیس، به این روش ذخیره کنید:
String FilePath = "Template Path" // Converting File to ByteArray byte[] FileBuffer = System.IO.File.ReadAllBytes(FilePath); // Now you can insert this file buffer to DB
الان، الگوی ما آمادهاست و میتوانیم از طریق برنامه، به این الگو دسترسی داشته باشیم و به آن پارامتر ارسال کنیم.
روش ارسال پارامترها به الگوهای Word
حالا
فرضا شما یک فرم دارید که از کاربر، اطلاعاتی را دریافت میکند و میخواهید همین
اطلاعات را به Word ارسال کنید. برای اینکار ابتدا باید
یک نمونه از الگویی را که طراحی کردهایم، داخل سیستم ذخیره کنیم. یعنی باید آنرا از
دیتابیس فراخوانی کنیم و آن آرایهی بایتی را، بر روی سیستم، تبدیل به فایل
کنیم. سپس از سمت برنامه، تمامی فیلدهای موجود در این الگو را خوانده و بجای تک تک آنها، مقدار مناسبی را قرار دهیم. در نهایت این فایل را توسط کدنویسی بر
روی سیستم کاربر ذخیره میکنیم. فایل را تبدیل به آرایه بایتی میکنیم، داخل
دیتابیس درج میکنیم و فایل را از سیستم کاربر حذف میکنیم.
بنابراین در ادامه ابتدا
Assembly مربوط به MicroSoft.Office.Interop.Word را به رفرنسهای پروژه اضافه
میکنیم و سربرگش را هم Using میکنیم.
حالا میرسیم به کد نویسی:
کدهای زیر را به صورت سراسری داخل فرم تعریف میکنیم:
//LOCATION OF THE TEMPLATE FILE ON THE MACHINE; Object oTemplatePath = string.Format("{0}\\NewDocument.dot", Application.StartupPath); //OBJECT OF MISSING "NULL VALUE" Object oMissing = System.Reflection.Missing.Value; //OBJECTS OF FALSE AND TRUE Object oTrue = true; Object oFalse = false; //CREATING OBJECTS OF WORD AND DOCUMENT Microsoft.Office.Interop.Word.Application oWord = null; Microsoft.Office.Interop.Word.Document oWordDoc = null;
// Fetching Template ByteArray From Database => Byte[] YourTemplateByteArray = Fetch Template; System.IO.File.WriteAllBytes(oTemplatePath.ToString(), YourByteArray); oWord = new Microsoft.Office.Interop.Word.Application(); oWordDoc = new Microsoft.Office.Interop.Word.Document(); //Adding A New Document From A Template oWordDoc = oWord.Documents.Add(ref oTemplatePath, ref oMissing, ref oMissing, ref oMissing); int iTotalFields = 0; // Finding Mailmerge Fields foreach(Microsoft.Office.Interop.Word.Field myMergeField in oWordDoc.Fields) { iTotalFields++; Microsoft.Office.Interop.Word.Range rngFieldCode = myMergeField.Code; String fieldText = rngFieldCode.Text; // Only Get The Mailmerge Fields if (fieldText.StartsWith(" MERGEFIELD")) { // Gives The Fieldnames as Entered in .DOT File string fieldName = fieldText.Substring(12, fieldText.IndexOf(" ", 12) - 12); switch (fieldName) { case "Letter_No": myMergeField.Select(); oWord.Selection.TypeText(txtLetterNo.Text); break; case "Letter_Date": myMergeField.Select(); oWord.Selection.TypeText(DateTime.Now); break; case "Letter_Has_Attachment": myMergeField.Select(); oWord.Selection.TypeText("دارد یا ندارد"); break; // And So On default: break; } } } //Showing The Document To The User oWord.Visible = true;
در ادامه یک دکمه را برای ذخیرهی فایل ورد قرار میدهیم. زمانیکه کاربر تایپ کردنش تمام شد و هنوز برنامهی ورد در حال اجراست، این دکمه را اجرا میکند. دقت کنید برنامهی ورد نباید بسته شود؛ باید باز باشد. بعد دکمهی ذخیره را میزنیم. با کدنویسی، برنامهی Word را خودمان میبندیم؛ نیازی به دخالت کاربر نیست.
oWordDoc.Save(); //Closing the file oWordDoc.Close(ref oFalse, ref oMissing, ref oMissing); //Quitting the application oWord.Quit(ref oMissing, ref oMissing, ref oMissing); byte[] FileBuffer = System.IO.File.ReadAllBytes(oTemplatePath.ToString ()); // Now Insert The FileBuffer Into Database as A Letter
خوب؛ کار تمام است! حالا فیلد FileBuffer را باید بسته به کدنویسی خودتان، داخل دیتابیس ذخیره کنید که برای بعدها بتوانید آنرا واکشی کرده و به کاربر نمایش دهید. این هم نمونهی نهایی جایگذاری فیلدها:
این آموزش را خیلی سال پیش در این تاپیک داخل فوروم برنامه نویس نوشته بودم.
- صفحهی اصلی
- منو
- یک صفحهی خوش آمدگویی
- صفحهی ورود و نمایش اطلاعات
<Window x:Class="TwoViews.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Title="MVVM Light View Switching" d:DesignHeight="300" d:DesignWidth="300" DataContext="{Binding Main, Source={StaticResource Locator}}" ResizeMode="NoResize" SizeToContent="WidthAndHeight" mc:Ignorable="d"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <ContentControl Content="{Binding CurrentViewModel}" /> <DockPanel Grid.Row="1" Margin="5"> <Button Width="75" Height="23" Command="{Binding SecondViewCommand}" Content="Second View" DockPanel.Dock="Right" /> <Button Width="75" Height="23" Command="{Binding FirstViewCommand}" Content="First View" DockPanel.Dock="Left" /> </DockPanel> </Grid> </Window>
/// This is our MainViewModel that is tied to the MainWindow via the /// ViewModelLocator class. /// </summary> public class MainViewModel : ViewModelBase { /// <summary> /// Static instance of one of the ViewModels. /// </summary> private static readonly SecondViewModel SecondViewModel = new SecondViewModel(); /// <summary> /// Static instance of one of the ViewModels. /// </summary> private static readonly FirstViewModel FirstViewModel = new FirstViewModel(); /// <summary> /// The current view. /// </summary> private ViewModelBase _currentViewModel; /// <summary> /// Default constructor. We set the initial view-model to 'FirstViewModel'. /// We also associate the commands with their execution actions. /// </summary> public MainViewModel() { CurrentViewModel = FirstViewModel; FirstViewCommand = new RelayCommand(ExecuteFirstViewCommand); SecondViewCommand = new RelayCommand(ExecuteSecondViewCommand); } /// <summary> /// The CurrentView property. The setter is private since only this /// class can change the view via a command. If the View is changed, /// we need to raise a property changed event (via INPC). /// </summary> public ViewModelBase CurrentViewModel { get { return _currentViewModel; } set { if (_currentViewModel == value) return; _currentViewModel = value; RaisePropertyChanged("CurrentViewModel"); } } /// <summary> /// Simple property to hold the 'FirstViewCommand' - when executed /// it will change the current view to the 'FirstView' /// </summary> public ICommand FirstViewCommand { get; private set; } /// <summary> /// Simple property to hold the 'SecondViewCommand' - when executed /// it will change the current view to the 'SecondView' /// </summary> public ICommand SecondViewCommand { get; private set; } /// <summary> /// Set the CurrentViewModel to 'FirstViewModel' /// </summary> private void ExecuteFirstViewCommand() { CurrentViewModel = FirstViewModel; } /// <summary> /// Set the CurrentViewModel to 'SecondViewModel' /// </summary> private void ExecuteSecondViewCommand() { CurrentViewModel = SecondViewModel; } }
<Application.Resources> <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" /> <!-- We define the data templates here so we can apply them across the entire application. The data template just says that if our data type is of a particular view-model type, then render the appropriate view. The framework takes care of this dynamically. Note that the DataContext for the underlying view is already set at this point, so the view (UserControl), doesn't need to have it's DataContext set directly. --> <DataTemplate DataType="{x:Type vm:SecondViewModel}"> <views:SecondView /> </DataTemplate> <DataTemplate DataType="{x:Type vm:FirstViewModel}"> <views:FirstView /> </DataTemplate> </Application.Resources>
PM> update-package T4MVC -Reinstall -ProjectName MVC5.Web PM> update-package Microsoft.AspNet.Mvc -ProjectName MVC5.Web PM> update-package Microsoft.Web.Infrastructure -ProjectName MVC5.Web
اگر این کار رو نکنید t4 خطا خواهد داد. البته با دستوری که در خود همین مطلب هم ذکر شده ، میتوان این خطا رو برطرف کرد :
Update-Package -Safe
یکی از متنهای خطایی که رخ میده به این صورت میباشد :
Loading the include file 'T4MVC.tt.hooks.t4' returned a null or empty string. The transformation will not be run.
.NET 8 Preview 4 is now available and includes many great new improvements to ASP.NET Core.
Here’s a summary of what’s new in this preview release:
Blazor
Streaming rendering with Blazor components
Handling form posts with Blazor SSR
Route to named elements in Blazor
Webcil packaging for Blazor WebAssembly apps
API authoring
Expanded support for form binding in minimal APIs
API project template includes .http file
Native AOT
Logging and exception handling in compile-time generated minimal APIs
ASP.NET Core top-level APIs annotated for trim warnings
Reduced app size with configurable HTTPS support
Worker Service template updates
Additional default services configured in the slim builder
API template JSON configuration changes
Support for JSON serialization of compiler-generated IAsyncEnumerable unspeakable types
Authentication and authorization
Identity API endpoints
Improved support for custom authorization policies with IAuthorizationRequirementData
ASP.NET Core metrics
For more details on the ASP.NET Core work planned for .NET 8 see the full ASP.NET Core roadmap for .NET 8 on GitHub.