طراحی افزونه پذیر با ASP.NET MVC 4.x/5.x - قسمت دوم
نویسنده: وحید نصیری
تاریخ: ۱۳۹۴/۰۱/۲۸ ۸:۵
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
PM> install-package Microsoft.AspNet.Web.Optimization
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using System.Web.Optimization;
namespace MvcPluginMasterApp.Common.WebToolkit
{
public class EmbeddedResourceTransform : IBundleTransform
{
private readonly IList<string> _resourceFiles;
private readonly string _contentType;
private readonly Assembly _assembly;
public EmbeddedResourceTransform(IList<string> resourceFiles, string contentType, Assembly assembly)
{
_resourceFiles = resourceFiles;
_contentType = contentType;
_assembly = assembly;
}
public void Process(BundleContext context, BundleResponse response)
{
var result = new StringBuilder();
foreach (var resource in _resourceFiles)
{
using (var stream = _assembly.GetManifestResourceStream(resource))
{
if (stream == null)
{
throw new KeyNotFoundException(string.Format("Embedded resource key: '{0}' not found in the '{1}' assembly.", resource, _assembly.FullName));
}
using (var reader = new StreamReader(stream))
{
result.Append(reader.ReadToEnd());
}
}
}
response.ContentType = _contentType;
response.Content = result.ToString();
}
}
} namespace MvcPluginMasterApp.Plugin1
{
public class Plugin1 : IPlugin
{
public EfBootstrapper GetEfBootstrapper()
{
return null;
}
public MenuItem GetMenuItem(RequestContext requestContext)
{
return new MenuItem
{
Name = "Plugin 1",
Url = new UrlHelper(requestContext).Action("Index", "Home", new { area = "NewsArea" })
};
}
public void RegisterBundles(BundleCollection bundles)
{
var executingAssembly = Assembly.GetExecutingAssembly();
// Mostly the default namespace and assembly name are the same
var assemblyNameSpace = executingAssembly.GetName().Name;
var scriptsBundle = new Bundle("~/Plugin1/Scripts",
new EmbeddedResourceTransform(new List<string>
{
assemblyNameSpace + ".Scripts.test1.js"
}, "application/javascript", executingAssembly));
if (!HttpContext.Current.IsDebuggingEnabled)
{
scriptsBundle.Transforms.Add(new JsMinify());
}
bundles.Add(scriptsBundle);
var cssBundle = new Bundle("~/Plugin1/Content",
new EmbeddedResourceTransform(new List<string>
{
assemblyNameSpace + ".Content.test1.css"
}, "text/css", executingAssembly));
if (!HttpContext.Current.IsDebuggingEnabled)
{
cssBundle.Transforms.Add(new CssMinify());
}
bundles.Add(cssBundle);
BundleTable.EnableOptimizations = true;
}
public void RegisterRoutes(RouteCollection routes)
{
}
public void RegisterServices(IContainer container)
{
}
}
}
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Web;
using System.Web.Routing;
namespace MvcPluginMasterApp.Common.WebToolkit
{
public class EmbeddedResourceRouteHandler : IRouteHandler
{
private readonly Assembly _assembly;
private readonly string _resourcePath;
private readonly TimeSpan _cacheDuration;
public EmbeddedResourceRouteHandler(Assembly assembly, string resourcePath, TimeSpan cacheDuration)
{
_assembly = assembly;
_resourcePath = resourcePath;
_cacheDuration = cacheDuration;
}
IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)
{
return new EmbeddedResourceHttpHandler(requestContext.RouteData, _assembly, _resourcePath, _cacheDuration);
}
}
public class EmbeddedResourceHttpHandler : IHttpHandler
{
private readonly RouteData _routeData;
private readonly Assembly _assembly;
private readonly string _resourcePath;
private readonly TimeSpan _cacheDuration;
public EmbeddedResourceHttpHandler(
RouteData routeData, Assembly assembly, string resourcePath, TimeSpan cacheDuration)
{
_routeData = routeData;
_assembly = assembly;
_resourcePath = resourcePath;
_cacheDuration = cacheDuration;
}
public bool IsReusable
{
get { return false; }
}
public void ProcessRequest(HttpContext context)
{
var routeDataValues = _routeData.Values;
var fileName = routeDataValues["file"].ToString();
var fileExtension = routeDataValues["extension"].ToString();
var manifestResourceName = string.Format("{0}.{1}.{2}", _resourcePath, fileName, fileExtension);
var stream = _assembly.GetManifestResourceStream(manifestResourceName);
if (stream == null)
{
throw new KeyNotFoundException(string.Format("Embedded resource key: '{0}' not found in the '{1}' assembly.", manifestResourceName, _assembly.FullName));
}
context.Response.Clear();
context.Response.ContentType = "application/octet-stream";
cacheIt(context.Response, _cacheDuration);
stream.CopyTo(context.Response.OutputStream);
}
private static void cacheIt(HttpResponse response, TimeSpan duration)
{
var cache = response.Cache;
var maxAgeField = cache.GetType().GetField("_maxAge", BindingFlags.Instance | BindingFlags.NonPublic);
if (maxAgeField != null) maxAgeField.SetValue(cache, duration);
cache.SetCacheability(HttpCacheability.Public);
cache.SetExpires(DateTime.Now.Add(duration));
cache.SetMaxAge(duration);
cache.AppendCacheExtension("must-revalidate, proxy-revalidate");
}
}
} namespace MvcPluginMasterApp.Plugin1
{
public class Plugin1 : IPlugin
{
public void RegisterRoutes(RouteCollection routes)
{
//todo: add custom routes.
var assembly = Assembly.GetExecutingAssembly();
// Mostly the default namespace and assembly name are the same
var nameSpace = assembly.GetName().Name;
var resourcePath = string.Format("{0}.Images", nameSpace);
routes.Insert(0,
new Route("NewsArea/Images/{file}.{extension}",
new RouteValueDictionary(new { }),
new RouteValueDictionary(new { extension = "png|jpg" }),
new EmbeddedResourceRouteHandler(assembly, resourcePath, cacheDuration: TimeSpan.FromDays(30))
));
}
}
} @{
ViewBag.Title = "From Plugin 1";
}
@Styles.Render("~/Plugin1/Content")
<h2>@ViewBag.Message</h2>
<div class="row">
Embedded image:
<img src="@Url.Content("~/NewsArea/Images/chart.png")" alt="clock" />
</div>
@section scripts
{
@Scripts.Render("~/Plugin1/Scripts")
}
public MenuItem GetMenuItem(RequestContext requestContext)
{
return new MenuItem
{
Name = "Plugin 1",
Url = new UrlHelper(requestContext).Action("Index", "Home", new { area = "NewsArea" })
};
} at MvcPluginMasterApp.Plugin1.Plugin1.RegisterRoutes(RouteCollection routes) at MvcPluginMasterApp.PluginsStart.Start() in c:\Users\Sirwan-Afifi\Desktop\MvcPluginMasterApp-Part2\MvcPluginMasterApp\App_Start\PluginsStart.cs:line 20
Copy "$(ProjectDir)$(OutDir)$(TargetName).*" "$(SolutionDir)MvcPluginMasterApp\bin\"
ممنون از راهنماییتون . یک اسکرین از صفحات گذاشتم .
public void RegisterRoutes(RouteCollection routes)
{
//....
routes.Insert(0,
new Route("NewsArea/Images/{file}.{extension}",
new RouteValueDictionary(new { }),
new RouteValueDictionary(new { extension = "png|jpg" }),
new EmbeddedResourceRouteHandler(assembly, resourcePath, cacheDuration: TimeSpan.FromDays(30))
));
} | Requested URL | http://localhost:46819/NewsArea/Images/1.jpg |
|---|---|
| Physical Path | C:\Users\Pouria\Desktop\mvc\AraxCMS\UI\NewsArea\Images\1.jpg |
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"> - فایلهای بوت استرپ هم در پروژهی اصلی هست دیگه. فایلهای مشترکی که قرار هست تمام افزونهها ازش استفاده کنند. به علاوه هم سیستم bundling (به صورت توکار) و هم سیستم فوق، اطلاعات رو کش میکنند(متد cacheIt). یعنی اینطور نیست که با هر درخواست از View، تمام اسکریپتها و تمام CSSها دوباره خونده میشن.
- مهم این هست که برنامه رو اجرا کنید، این سیستم یکپارچه هست. همینقدر که اسکریپتها یا CSSها در HTML نهایی تولیدی وجود داشته باشند، برنامه کار میکنه. اینجا دید سیستمی باید داشته باشید. این یک سیستم هست که از همکاری اجزای مختلف اون یک هدف واحد حاصل میشه.