এই একজন আমাকে আগ্রহী এবং অবশেষে আমি এটি সন্ধান করার সুযোগ পেয়েছি। অন্যান্য লোকেরা আপাতদৃষ্টিতে বুঝতে পারেন নি যে এই দৃষ্টিভঙ্গি খুঁজে বের করার একটি সমস্যা, রাউটিংয়ের কোনও সমস্যা নয় নিজেই নয় - এবং এটি সম্ভবত আপনার প্রশ্নের শিরোনাম নির্দেশ করে যে এটি রাউটিং সম্পর্কে।
যাই হোক না কেন, এটি একটি ভিউ-সম্পর্কিত সমস্যা, তাই আপনি যা চান তা পাওয়ার একমাত্র উপায় হ'ল ডিফল্ট ভিউ ইঞ্জিনটিকে ওভাররাইড করে । সাধারণত, আপনি যখন এটি করেন, এটি আপনার ভিউ ইঞ্জিনটি স্যুইচ করার সহজ উদ্দেশ্যে (যেমন স্পার্ক, এনএইচএল ইত্যাদি)। এক্ষেত্রে, আমাদের দেখার প্রয়োজন যুক্তি-নির্মাণের যুক্তিটি নয় , ক্লাসে পদ্ধতি FindPartialView
এবং FindView
পদ্ধতি VirtualPathProviderViewEngine
।
আপনি আপনার ভাগ্যবান তারাগুলি ধন্যবাদ জানাতে পারেন যে এই পদ্ধতিগুলি বাস্তবে ভার্চুয়াল, কারণ এর সমস্ত কিছু VirtualPathProviderViewEngine
এমনকি অ্যাক্সেসযোগ্য নয় - এটি ব্যক্তিগত, এবং এটি এটিকে খুব করে তোলে অনুসন্ধান যুক্তিটিকে ওভাররাইড করতে বিরক্তিকর করে কারণ আপনাকে ইতিমধ্যে কোডটির অর্ধেকটি আবার লিখতে হবে যা ইতিমধ্যে আপনি যদি এটি লোকেশন ক্যাশে এবং অবস্থানের ফর্ম্যাটগুলির সাথে দুর্দান্ত খেলতে চান তবে এটি লেখা হয়েছে। রিফ্লেক্টরে কিছু খননের পরে অবশেষে আমি একটি কার্যনির্বাহী সমাধান নিয়ে আসতে সক্ষম হয়েছি।
আমি এখানে যা করেছি তা হ'ল প্রথমে একটি বিমূর্ততা তৈরি করা AreaAwareViewEngine
যা সরাসরি VirtualPathProviderViewEngine
পরিবর্তে থেকে আসে WebFormViewEngine
। আমি এটি করেছি যাতে আপনি পরিবর্তে (বা যাই হোক না কেন) স্পার্ক ভিউ তৈরি করতে চান তবে আপনি এখনও এই শ্রেণিকে বেস টাইপ হিসাবে ব্যবহার করতে পারেন।
নীচের কোডটি বেশ দীর্ঘ-বায়ুযুক্ত, সুতরাং এটি আসলে কী করে তা আপনাকে একটি দ্রুত সংক্ষিপ্ত বিবরণ দেওয়ার জন্য: এটি আপনাকে {2}
অবস্থান বিন্যাসে একটি স্থান দিতে দেয় যা একইরূপে এলাকার নামের সাথে মিলে যায়{1}
নিয়ামকের নামের সাথে মিলে যায়। এটাই! এই জন্য আমাদের এই সমস্ত কোডটি লিখতে হয়েছিল:
BaseAreaAwareViewEngine.cs
public abstract class BaseAreaAwareViewEngine : VirtualPathProviderViewEngine
{
private static readonly string[] EmptyLocations = { };
public override ViewEngineResult FindView(
ControllerContext controllerContext, string viewName,
string masterName, bool useCache)
{
if (controllerContext == null)
{
throw new ArgumentNullException("controllerContext");
}
if (string.IsNullOrEmpty(viewName))
{
throw new ArgumentNullException(viewName,
"Value cannot be null or empty.");
}
string area = getArea(controllerContext);
return FindAreaView(controllerContext, area, viewName,
masterName, useCache);
}
public override ViewEngineResult FindPartialView(
ControllerContext controllerContext, string partialViewName,
bool useCache)
{
if (controllerContext == null)
{
throw new ArgumentNullException("controllerContext");
}
if (string.IsNullOrEmpty(partialViewName))
{
throw new ArgumentNullException(partialViewName,
"Value cannot be null or empty.");
}
string area = getArea(controllerContext);
return FindAreaPartialView(controllerContext, area,
partialViewName, useCache);
}
protected virtual ViewEngineResult FindAreaView(
ControllerContext controllerContext, string areaName, string viewName,
string masterName, bool useCache)
{
string controllerName =
controllerContext.RouteData.GetRequiredString("controller");
string[] searchedViewPaths;
string viewPath = GetPath(controllerContext, ViewLocationFormats,
"ViewLocationFormats", viewName, controllerName, areaName, "View",
useCache, out searchedViewPaths);
string[] searchedMasterPaths;
string masterPath = GetPath(controllerContext, MasterLocationFormats,
"MasterLocationFormats", masterName, controllerName, areaName,
"Master", useCache, out searchedMasterPaths);
if (!string.IsNullOrEmpty(viewPath) &&
(!string.IsNullOrEmpty(masterPath) ||
string.IsNullOrEmpty(masterName)))
{
return new ViewEngineResult(CreateView(controllerContext, viewPath,
masterPath), this);
}
return new ViewEngineResult(
searchedViewPaths.Union<string>(searchedMasterPaths));
}
protected virtual ViewEngineResult FindAreaPartialView(
ControllerContext controllerContext, string areaName,
string viewName, bool useCache)
{
string controllerName =
controllerContext.RouteData.GetRequiredString("controller");
string[] searchedViewPaths;
string partialViewPath = GetPath(controllerContext,
ViewLocationFormats, "PartialViewLocationFormats", viewName,
controllerName, areaName, "Partial", useCache,
out searchedViewPaths);
if (!string.IsNullOrEmpty(partialViewPath))
{
return new ViewEngineResult(CreatePartialView(controllerContext,
partialViewPath), this);
}
return new ViewEngineResult(searchedViewPaths);
}
protected string CreateCacheKey(string prefix, string name,
string controller, string area)
{
return string.Format(CultureInfo.InvariantCulture,
":ViewCacheEntry:{0}:{1}:{2}:{3}:{4}:",
base.GetType().AssemblyQualifiedName,
prefix, name, controller, area);
}
protected string GetPath(ControllerContext controllerContext,
string[] locations, string locationsPropertyName, string name,
string controllerName, string areaName, string cacheKeyPrefix,
bool useCache, out string[] searchedLocations)
{
searchedLocations = EmptyLocations;
if (string.IsNullOrEmpty(name))
{
return string.Empty;
}
if ((locations == null) || (locations.Length == 0))
{
throw new InvalidOperationException(string.Format("The property " +
"'{0}' cannot be null or empty.", locationsPropertyName));
}
bool isSpecificPath = IsSpecificPath(name);
string key = CreateCacheKey(cacheKeyPrefix, name,
isSpecificPath ? string.Empty : controllerName,
isSpecificPath ? string.Empty : areaName);
if (useCache)
{
string viewLocation = ViewLocationCache.GetViewLocation(
controllerContext.HttpContext, key);
if (viewLocation != null)
{
return viewLocation;
}
}
if (!isSpecificPath)
{
return GetPathFromGeneralName(controllerContext, locations, name,
controllerName, areaName, key, ref searchedLocations);
}
return GetPathFromSpecificName(controllerContext, name, key,
ref searchedLocations);
}
protected string GetPathFromGeneralName(ControllerContext controllerContext,
string[] locations, string name, string controllerName,
string areaName, string cacheKey, ref string[] searchedLocations)
{
string virtualPath = string.Empty;
searchedLocations = new string[locations.Length];
for (int i = 0; i < locations.Length; i++)
{
if (string.IsNullOrEmpty(areaName) && locations[i].Contains("{2}"))
{
continue;
}
string testPath = string.Format(CultureInfo.InvariantCulture,
locations[i], name, controllerName, areaName);
if (FileExists(controllerContext, testPath))
{
searchedLocations = EmptyLocations;
virtualPath = testPath;
ViewLocationCache.InsertViewLocation(
controllerContext.HttpContext, cacheKey, virtualPath);
return virtualPath;
}
searchedLocations[i] = testPath;
}
return virtualPath;
}
protected string GetPathFromSpecificName(
ControllerContext controllerContext, string name, string cacheKey,
ref string[] searchedLocations)
{
string virtualPath = name;
if (!FileExists(controllerContext, name))
{
virtualPath = string.Empty;
searchedLocations = new string[] { name };
}
ViewLocationCache.InsertViewLocation(controllerContext.HttpContext,
cacheKey, virtualPath);
return virtualPath;
}
protected string getArea(ControllerContext controllerContext)
{
// First try to get area from a RouteValue override, like one specified in the Defaults arg to a Route.
object areaO;
controllerContext.RouteData.Values.TryGetValue("area", out areaO);
// If not specified, try to get it from the Controller's namespace
if (areaO != null)
return (string)areaO;
string namespa = controllerContext.Controller.GetType().Namespace;
int areaStart = namespa.IndexOf("Areas.");
if (areaStart == -1)
return null;
areaStart += 6;
int areaEnd = namespa.IndexOf('.', areaStart + 1);
string area = namespa.Substring(areaStart, areaEnd - areaStart);
return area;
}
protected static bool IsSpecificPath(string name)
{
char ch = name[0];
if (ch != '~')
{
return (ch == '/');
}
return true;
}
}
এখন যেমন বলা হয়েছে, এটি কোনও কংক্রিট ইঞ্জিন নয়, তাই আপনাকে এটিও তৈরি করতে হবে। ভাগ্যক্রমে, এই অংশটি অনেক সহজ, আমাদের কেবলমাত্র ডিফল্ট ফর্ম্যাটগুলি সেট করা এবং দর্শনগুলি তৈরি করতে হবে:
AreaAwareViewEngine.cs
public class AreaAwareViewEngine : BaseAreaAwareViewEngine
{
public AreaAwareViewEngine()
{
MasterLocationFormats = new string[]
{
"~/Areas/{2}/Views/{1}/{0}.master",
"~/Areas/{2}/Views/{1}/{0}.cshtml",
"~/Areas/{2}/Views/Shared/{0}.master",
"~/Areas/{2}/Views/Shared/{0}.cshtml",
"~/Views/{1}/{0}.master",
"~/Views/{1}/{0}.cshtml",
"~/Views/Shared/{0}.master"
"~/Views/Shared/{0}.cshtml"
};
ViewLocationFormats = new string[]
{
"~/Areas/{2}/Views/{1}/{0}.aspx",
"~/Areas/{2}/Views/{1}/{0}.ascx",
"~/Areas/{2}/Views/{1}/{0}.cshtml",
"~/Areas/{2}/Views/Shared/{0}.aspx",
"~/Areas/{2}/Views/Shared/{0}.ascx",
"~/Areas/{2}/Views/Shared/{0}.cshtml",
"~/Views/{1}/{0}.aspx",
"~/Views/{1}/{0}.ascx",
"~/Views/{1}/{0}.cshtml",
"~/Views/Shared/{0}.aspx"
"~/Views/Shared/{0}.ascx"
"~/Views/Shared/{0}.cshtml"
};
PartialViewLocationFormats = ViewLocationFormats;
}
protected override IView CreatePartialView(
ControllerContext controllerContext, string partialPath)
{
if (partialPath.EndsWith(".cshtml"))
return new System.Web.Mvc.RazorView(controllerContext, partialPath, null, false, null);
else
return new WebFormView(controllerContext, partialPath);
}
protected override IView CreateView(ControllerContext controllerContext,
string viewPath, string masterPath)
{
if (viewPath.EndsWith(".cshtml"))
return new RazorView(controllerContext, viewPath, masterPath, false, null);
else
return new WebFormView(controllerContext, viewPath, masterPath);
}
}
নোট করুন যে আমরা স্ট্যান্ডার্ডটিতে কয়েকটি এন্ট্রি যুক্ত করেছি ViewLocationFormats
। এগুলি {2}
হ'ল নতুন এন্ট্রি, যেখানে আমরা যে {2}
নথিটি রেখেছি তা ম্যাপ করা হবে । আমি একা রেখেছি , তবে আপনি চাইলে আপনি তা পরিবর্তন করতে পারেন।area
RouteData
MasterLocationFormats
global.asax
এই ভিউ ইঞ্জিনটি নিবন্ধ করার জন্য এখন আপনার সংশোধন করুন :
Global.asax.cs
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new AreaAwareViewEngine());
}
... এবং ডিফল্ট রুটটি নিবন্ধ করুন:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Area",
"",
new { area = "AreaZ", controller = "Default", action = "ActionY" }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
}
এখন AreaController
আমরা কেবল উল্লেখ করা তৈরি করুন :
DefaultController.cs (~ / নিয়ন্ত্রণকারী / এ)
public class DefaultController : Controller
{
public ActionResult ActionY()
{
return View("TestView");
}
}
স্পষ্টতই আমাদের ডিরেক্টরি কাঠামো এবং এটির সাথে দেখতে প্রয়োজন - আমরা এটি অতি সাধারণ রাখব:
টেস্টভিউ.এএসপিএক্স (~ / অঞ্চলসমূহ / এরিয়াজেড / ভিউ / ডিফল্ট / বা ~ / অঞ্চল / অঞ্চলজ / দর্শন / ভাগ করা /)
<%@ Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
<h2>TestView</h2>
This is a test view in AreaZ.
এবং এটাই. অবশেষে, আমরা শেষ করেছি ।
বেশিরভাগ ক্ষেত্রে, আপনার কেবলমাত্র নেওয়া BaseAreaAwareViewEngine
এবং AreaAwareViewEngine
এটি কোনও এমভিসি প্রকল্পে ফেলতে সক্ষম হওয়া উচিত , সুতরাং এটি সম্পন্ন করতে প্রচুর কোড লাগলেও, আপনাকে কেবল একবার এটি লিখতে হবে। এর পরে, এটি global.asax.cs
আপনার সাইটের কাঠামোটি কয়েক লাইন সম্পাদনা এবং তৈরি করার বিষয় just