2015-03-24 3 views
0

Я хочу создать настраиваемый элемент управления для совместного использования несколькими проектами MVC. Этот пользовательский контроль - это просто (на мой взгляд) частичное представление с моделью и бизнес-логикой в ​​классах, стоящих за ней. Сайты MVC может включать в себя ссылку на эту библиотеку классов и в их .cshtml просто называют @Html.Partial("CoolControl").MVC 5 - Как создать портативный пользовательский элемент управления (частичный)

То, что я пытаюсь сейчас проект библиотеки классов, с MVC -> Models folder с моей моделью кода и папку Views с .cshtml элемента управления код.

Если я правильно помню, частичные файлы идут в папке веб-сайта MVC, поэтому их можно найти. Но здесь частичная жизнь вне этого.

Как мне показать MVC внешнюю библиотеку для частичного просмотра? Это даже лучший способ сделать это?

Есть ли лучший способ создания переносных элементов управления в MVC?

ответ

1

Доля частичных представлений для нескольких проектов в библиотеке классов не так проста. Прежде всего, необходимо создать виртуальный файл и провайдер виртуального

public class AspNetVirtualFile : VirtualFile 
{ 
private string path; 

public AspNetVirtualFile(string virtualPath) 
    : base(virtualPath) 
{ 
    path = VirtualPathUtility.ToAppRelative(virtualPath); 
} 

public override System.IO.Stream Open() 
{ 
    var parts = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); 

    var assemblyName = parts[2]; 
    var resourceName = parts[3]; 

    assemblyName = Path.Combine(HttpRuntime.BinDirectory, assemblyName); 
    var assembly = Assembly.LoadFile(assemblyName + ".dll"); 

    if (assembly != null) 
    { 
     return assembly.GetManifestResourceStream(resourceName); 
    } 

    return null; 
} 
} 

VirtualProvider

public class AspNetVirtualProvider : VirtualPathProvider 
{ 
public const string StartPath = "~/UserControls/"; 
public const string Path = "~/UserControls/{0}/{1}"; 

public AspNetVirtualProvider() { } 

private bool IsEmbeddedResourcePath(string virtualPath) 
{ 
    try 
    { 
     var checkPath = VirtualPathUtility.ToAppRelative(virtualPath); 
     return checkPath.StartsWith(StartPath, StringComparison.InvariantCultureIgnoreCase); 
    } 
    catch 
    { 

    } 
    return false; 
} 

public override bool FileExists(string virtualPath) 
{ 
    return IsEmbeddedResourcePath(virtualPath) || base.FileExists(virtualPath); 
} 

public override VirtualFile GetFile(string virtualPath) 
{ 
    if (IsEmbeddedResourcePath(virtualPath)) 
    { 
     return new AspNetVirtualFile(virtualPath); 
    } 
    else 
    { 
     return base.GetFile(virtualPath); 
    } 
} 

public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart) 
{ 
    if (IsEmbeddedResourcePath(virtualPath)) 
    { 
     return null; 
    } 
    else 
    { 
     return base.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart); 
    } 
} 
} 

Посмотреть, что поставщик будет найти файлы в папке UserControls в этой общей .dll, вы можете изменить, если вы хотите. В Global.asax Application_Start:

System.Web.Hosting.HostingEnvironment.RegisterVirtualPathProvider(new AspNetVirtualProvider()); 

Создание HtmlHelper, не забывайте о помощи System.Web.Mvc.Html:

public static class HtmlHelpers 
{ 
public static void SharedRenderPartial(this HtmlHelper h, string assemblyName, string fileName, object model) 
{ 
    h.RenderPartial(String.Format(AspNetVirtualProvider.Path, assemblyName, fileName), model); 
} 
} 

Теперь в вашем View вы можете сделать:

@{ Html.SharedRenderPartial("My.Qualified.Assembly", String.Format("My.Qualified.Assembly.UserControls.{0}", "_ViewName.cshtml"), Model); } 

Теперь вы создаете cshtml в папке UserControls в проекте My.Qualified.Assembly, вам необходимо изменить файл BuildAction на EmbededResource. По вашему мнению, вам нужно будет объяснить, добавьте использование и @inherits System.Web.Mvc.WebViewPage.

+1

Я ценю усилия, с которыми вы столкнулись, с ответом, но он быстро говорит мне, что это слишком много для того, чего я хочу достичь. – VictorySaber

+0

Эта конфигурация вам нужно сделать только один раз, после этого вам просто нужно использовать. Если я понял ваш вопрос, ваши взгляды находятся в другом проекте? Оверкилл, который вы сказали, является решением, которое я сделал, или вы сдадите, чтобы поместить пользовательские элементы в другую библиотеку? Другой способ сделать это - скопировать ссылку на ваши общие файлы в ваш проект. –

0

Я считаю, что создание библиотеки классов не является хорошим способом создания пользовательских контролей. Лучше создать nuget package. Он позволяет добавлять дополнительные файлы в папки проектов и решать проблемы с зависимостями и будущими обновлениями ваших элементов управления.

Если вы whould хотите найти ваш PartialViews в отличаешься папкой по умолчанию, чем, лучшее решение будет наследоваться от RazorViewEngine, создавать свою собственную маршрутизацию и зарегистрировать его в MVC ViewEngines. Вот как это сделать: good article.

+0

На самом деле, чтобы найти их в другой папке, вы можете создать свой собственный ViewEngine (просто получить RazorViewEngine) и рассказать ему, где искать. Затем зарегистрируйте его в Application_Start(). Вы правильно говорите, что библиотека классов не является хорошим способом сделать это! – VictorySaber

+0

@VictorySaber yeap, вы правы, это может быть очень гибким. Но может быть, что вы должны написать много кода реализации в этом случае. –

Смежные вопросы