Performance در AngularJS قدم اول
خوب ابتدا فرض میکنیم برای نمایش تصاویر چند حالت داریم مثلا کوچک، متوسط، بزرگ و حالت واقعی (اندازه اصلی).
البته دقت نمایید که این طبقه بندی فرضی بوده و ممکن است برای پروژههای مختلف این طبقه بندی متفاوت باشد. (در این پست قصد فقط اشنایی با تغییر اندازه تصاویر است و شاید کد به درستی refactor نشده باشد).
برای تغییر اندازه تصاویر در زمان اجرا یکی از روش ها، میتواند استفاده از Handler باشد. خوب برای ایجاد Handler ابتدا در پروژه وب خود بروی پروژه راست کلیک کرده، و گزینه New Item را برگزینید، و در پنجره ظاهر شده مانند تصویر زیر گزینه Generic Handler را انتخاب نمایید.
پس از ایجاد هندلر، فایل کد آن مانند زیر خواهد بود، ما باید کدهای خود را در متد ProcessRequestبنویسیم.
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace PWS.UI.Handler { /// <summary> /// Summary description for PhotoHandler /// </summary> public class PhotoHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; context.Response.Write("Hello World"); } public bool IsReusable { get { return false; } } } }
خوب برای نوشتن کد در این مرحله ما باید چند کار انجام دهیم.
1- گرفتن پارامترهای ورودی کاربر جهت تغییر سایز از طریق روشهای انتقال مقادیر بین صفحات (در اینجا استفاده از Query String ).
2-بازیابی تصویر از دیتابیس یا از دیسک به صورت یک آرایه بایتی.
3- تغییر اندازه تصویر مرحله 2 و ارسال تصویر به خروجی.
using System; using System.Data.SqlClient; using System.Diagnostics; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.Globalization; using System.IO; using System.Web; namespace PWS.UI.Handler { /// <summary> /// Summary description for PhotoHandler /// </summary> public class PhotoHandler : IHttpHandler { /// <summary> /// بازیابی تصویر اصلی از بانک اطلاعاتی /// </summary> /// <param name="photoId">کد تصویر</param> /// <returns></returns> private byte[] GetImageFromDatabase(int photoId) { using (var connection = new SqlConnection("ConnectionString")) { using (var command = new SqlCommand("Select Photo From tblPhotos Where Id = @PhotoId", connection)) { command.Parameters.Add(new SqlParameter("@PhotoId", photoId)); connection.Open(); var result = command.ExecuteScalar(); return ((byte[])result); } } } /// <summary> /// بازیابی فایل از دیسک /// </summary> /// <param name="photoId">با فرض اینکه نام فایل این است</param> /// <returns></returns> private byte[] GetImageFromDisk(string photoId /* or somting */) { using (var sourceStream = new FileStream("Original File Path + id", FileMode.Open, FileAccess.Read)) { return StreamToByteArray(sourceStream); } } /// <summary> /// Streams to byte array. /// </summary> /// <param name="inputStream">The input stream.</param> /// <returns></returns> /// <exception cref="System.ArgumentException"></exception> static byte[] StreamToByteArray(Stream inputStream) { if (!inputStream.CanRead) { throw new ArgumentException(); } // This is optional if (inputStream.CanSeek) { inputStream.Seek(0, SeekOrigin.Begin); } var output = new byte[inputStream.Length]; int bytesRead = inputStream.Read(output, 0, output.Length); Debug.Assert(bytesRead == output.Length, "Bytes read from stream matches stream length"); return output; } /// <summary> /// Enables processing of HTTP Web requests by a custom HttpHandler that implements the <see cref="T:System.Web.IHttpHandler" /> interface. /// </summary> /// <param name="context">An <see cref="T:System.Web.HttpContext" /> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param> public void ProcessRequest(HttpContext context) { // Set up the response settings context.Response.ContentType = "image/jpeg"; context.Response.Cache.SetCacheability(HttpCacheability.Public); context.Response.BufferOutput = false; // مرحله اول int size = 0; switch (context.Request.QueryString["Size"]) { case "S": size = 100; //100px break; case "M": size = 198; //198px break; case "L": size = 500; //500px break; } byte[] changedImage; var id = Convert.ToInt32(context.Request.QueryString["PhotoId"]); byte[] sourceImage = GetImageFromDatabase(id); // یا //byte[] sourceImage = GetImageFromDisk(id.ToString(CultureInfo.InvariantCulture)); //مرحله 2 if (size != 0) //غیر از حالت واقعی تصویر { changedImage = Helpers.ResizeImageFile(sourceImage, size, ImageFormat.Jpeg); } else { changedImage = (byte[])sourceImage.Clone(); } // مرحله 3 if (changedImage == null) return; context.Response.AddHeader("Content-Length", changedImage.Length.ToString(CultureInfo.InvariantCulture)); context.Response.BinaryWrite(changedImage); } public bool IsReusable { get { return false; } } } }
2- متد GetImageFromDisk: این متد نام تصویر (با فرض اینکه یک عدد میباشد) را به عنوان پارامتر گرفته و آنرا بازیابی میکند (در صورتی که تصویر در دیسک ذخیره شده باشد.)
3- متد StreamToByteArray: زمانی که تصویر از فایل خوانده میشود به صورت Stream است این متد یک Stream را گرفته و تبدیل به یک آرایه بایتی میکند.
در نهایت در متد ProcessRequestتصویر خوانده شده با توجه به پارامترهای ورودی تغییر اندازه داده شده و در نهایت به خروجی نوشته میشود.
برای استفاده این هندلر، کافی است در توصیر خود به عنوان مسیر رشته ای شبیه زیر وارد نمایید:
PhotoHandler.ashx?PhotoId=10&Size=S مانند <img src='PhotoHandler.ashx?PhotoId=10&Size=S' alt='تصویر ازمایشی' />
نظرات اقای موسوی تا حدودی اعمال شد و در پست تغییراتی انجام شد.
موفق وموید باشید
آشنایی با NHibernate - قسمت هشتم
http://en.هشام.com/post/build-customizable-language-switcher-tag-helper-with-bootstrap
WebRequest wr = WebRequest.Create(uri); using (WebResponse response = wr.GetResponse()) { }
The remote name could not be resolved: 'en.هشام.com'
البته ممکن است کد فوق را بر روی ویندوزهای جدید بدون مشکل اجرا کنید. علت اینجا است که اگر از ویندوزهای قبل از ویندوز سرور 2012 استفاده میکنید، دات نت فریم ورک از RFC 3490 استفاده میکند؛ در غیراینصورت از RFC 5891 (فقط برای Windows 8, Windows 8.1, Windows 10, or Windows Server 2012)، با این تفاوتها.
روش رفع آن هم فعال سازی پردازش این نوع دامنهها (بر روی تمام ویندوزها) در فایلهای app.config و یا web.config به صورت زیر است:
<configuration> <uri> <idn enabled="All" /> <iriParsing enabled="true" /> </uri> </configuration>
var unicode = @"en.هشام.com"; var mapping = new IdnMapping(); // IDN = Internationalizing Domain Names var ascii = mapping.GetAscii(unicode); Console.WriteLine(ascii); string convertedBackToUnicode = mapping.GetUnicode(ascii); Console.WriteLine(convertedBackToUnicode);
قالب ادمین مبتنی بر angular material
کلیدهای مربوط به Request
ضروری؟ | نام کلید | مقدار |
بله | "owin.RequestBody" | یک Stream همراه با request body. اگر body برای request وجود نداشته باشد، Stream.Null به عنوان placeholder قابل استفاده است. |
بله | "owin.RequestHeaders" | یک دیکشنری به صورت IDictionary<string, string[]> از هدرهای درخواست. |
بله | "owin.RequestMethod" | رشتهایی حاوی نوع فعل متد HTTP مربوط به درخواست (مانند GET and POST ) |
بله | "owin.RequestPath" | path درخواست شده به صورت string |
بله | "owin.RequestPathBase" | قسمتی از path درخواست به صورت string |
بله | "owin.RequestProtocol" | نام و نسخهی پروتکل (مانند HTTP/1.0 or HTTP/1.1 ) |
بله | "owin.RequestQueryString" | رشتهای حاوی query string ؛ بدون علامت ? (مانند foo=bar&baz=quux ) |
بله | "owin.RequestScheme" | رشتهایی حاوی URL scheme استفاده شده در درخواست (مانند HTTP or HTTPS ) |
ضروری؟ | نام کلید | مقدار |
بله | "owin.ResponseBody" | یک Stream جهت نوشتن response body در خروجی |
بله | "owin.ResponseHeaders" | یک دیکشنری به صورت IDictionary<string, string[]> از هدرهای response |
خیر | "owin.ResponseStatusCode" | یک عدد صحیح حاوی کد وضعیت HTTP response ؛ حالت پیشفرض 200 است. |
خیر | "owin.ResponseReasonPhrase" | یک رشته حاوی reason phrase مربوط به status code ؛ اگر خالی باشد در نتیجه سرور بهتر است آن را مقداردهی کند. |
خیر | "owin.ResponseProtocol" | یک رشته حاوی نام و نسخهی پروتکل (مانند HTTP/1.0 or HTTP/1.1 )؛ اگر خالی باشد؛ “owin.RequestProtocol” به عنوان مقدار پیشفرض در نظر گرفته خواهد شد. |
<package id="Microsoft.Owin" version="3.0.1" targetFramework="net461" /> <package id="Microsoft.Owin.Host.SystemWeb" version="3.0.1" targetFramework="net461" /> <package id="Owin" version="1.0" targetFramework="net461" />
using Owin; namespace SimpleOwinWebApp { public class Startup { public void Configuration(IAppBuilder app) { } } }
using Owin; namespace SimpleOwinWebApp { public class Startup { public void Configuration(IAppBuilder app) { app.Use(async (ctx, next) => { await ctx.Response.WriteAsync("Hello"); }); } }
Func<IOwinContext, Func<Task>, Task> handler
app.Use(async (ctx, next) => { var response = ctx.Environment["owin.ResponseBody"] as Stream; using (var writer = new StreamWriter(response)) { await writer.WriteAsync("Hello"); } });
using System; using Microsoft.Owin.Hosting; namespace SimpleOwinConsoleApp { class Program { static void Main(string[] args) { using (WebApp.Start<Startup>("http://localhost:12345")) { Console.WriteLine("Listening to port 12345"); Console.WriteLine("Press Enter to end..."); Console.ReadLine(); } } } }
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace SimpleOwinCoreApp { public class Startup { public void ConfigureServices(IServiceCollection services) { } public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.Run(async (context) => { await context.Response.WriteAsync("Hello World!"); }); } } }
using System.Threading.Tasks; using Microsoft.AspNetCore.Http; namespace SimpleOwinCoreApp.Middlewares { public class SimpleMiddleware { private readonly RequestDelegate _next; public SimpleMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext ctx) { // قبل از فراخوانی میانافزار بعدی await ctx.Response.WriteAsync("Hello DNT!"); await _next(ctx); // بعد از فراخوانی میانافزار بعدی } } }
app.UseMiddleware<SimpleMiddleware>();
"Microsoft.AspNetCore.Owin": "1.0.0"
app.UseOwin(pipeline => { pipeline(next => new MyKatanaBasedMiddleware(next).Invoke) });
using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; namespace SimpleOwinAspNetCore.Middleware { public class IpBlockerMiddleware { private readonly RequestDelegate _next; private readonly IpBlockerOptions _options; public IpBlockerMiddleware(RequestDelegate next, IpBlockerOptions options) { _next = next; _options = options; } public async Task Invoke(HttpContext context) { var ipAddress = context.Request.Host.Host; if (IsBlockedIpAddress(ipAddress)) { context.Response.StatusCode = 403; await context.Response.WriteAsync("Forbidden : The server understood the request, but It is refusing to fulfill it."); return; } await _next.Invoke(context); } private bool IsBlockedIpAddress(string ipAddress) { return _options.Ips.Any(ip => ip == ipAddress); } } }
using System.Collections.Generic; namespace SimpleOwinAspNetCore.Middleware { public class IpBlockerOptions { public IpBlockerOptions() { Ips = new[] { "192.168.1.1" }; } public IList<string> Ips { get; set; } } }
using System.Linq; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Configuration; namespace SimpleOwinAspNetCore.Middleware { public static class IpBlockerExtensions { public static IApplicationBuilder UseIpBlocker(this IApplicationBuilder builder, IConfigurationRoot configuration, IpBlockerOptions options = null) { return builder.UseMiddleware<IpBlockerMiddleware>(options ?? new IpBlockerOptions { Ips = configuration.GetSection("block_list").GetChildren().Select(p => p.Value).ToArray() }); } } }
{ "block_list": [ "192.168.1.1", "localhost", "127.0.0.1", "172.16.132.151" ] }
public IConfigurationRoot Configuration { set; get; } public Startup(IHostingEnvironment env) { var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("blockedIps.json"); Configuration = builder.Build(); }
app.UseIpBlocker(Configuration);
Nebular is a great toolkit if you build Rich UI web-application based on Angular, and want to bootstrap your development using essential features out of the box. It provides you with a set of native Angular components, themeable components, authentication and security layers easily configurable for your API. At the same time, Nebular allows you to use it together with any other UI library you choose.