Rename "Future.Modules.Packaging" to "Orchard.Packaging"

--HG--
branch : dev
rename : src/Orchard.Web/Modules/Futures.Modules.Packaging/AdminMenu.cs => src/Orchard.Web/Modules/Orchard.Packaging/AdminMenu.cs
rename : src/Orchard.Web/Modules/Futures.Modules.Packaging/Commands/PackagingCommands.cs => src/Orchard.Web/Modules/Orchard.Packaging/Commands/GalleryCommands.cs
rename : src/Orchard.Web/Modules/Futures.Modules.Packaging/Commands/PackagingCommands.cs => src/Orchard.Web/Modules/Orchard.Packaging/Commands/PackagingCommands.cs
rename : src/Orchard.Web/Modules/Futures.Modules.Packaging/Controllers/DownloadStreamResult.cs => src/Orchard.Web/Modules/Orchard.Packaging/Controllers/DownloadStreamResult.cs
rename : src/Orchard.Web/Modules/Futures.Modules.Packaging/Controllers/PackagingController.cs => src/Orchard.Web/Modules/Orchard.Packaging/Controllers/PackagingController.cs
rename : src/Orchard.Web/Modules/Futures.Modules.Packaging/Module.txt => src/Orchard.Web/Modules/Orchard.Packaging/Module.txt
rename : src/Orchard.Web/Modules/Futures.Modules.Packaging/Futures.Modules.Packaging.csproj => src/Orchard.Web/Modules/Orchard.Packaging/Orchard.Packaging.csproj
rename : src/Orchard.Web/Modules/Futures.Modules.Packaging/Properties/AssemblyInfo.cs => src/Orchard.Web/Modules/Orchard.Packaging/Properties/AssemblyInfo.cs
rename : src/Orchard/Packaging/AtomExtensions.cs => src/Orchard.Web/Modules/Orchard.Packaging/Services/AtomExtensions.cs
rename : src/Orchard/Packaging/IPackageBuilder.cs => src/Orchard.Web/Modules/Orchard.Packaging/Services/IPackageBuilder.cs
rename : src/Orchard/Packaging/IPackageExpander.cs => src/Orchard.Web/Modules/Orchard.Packaging/Services/IPackageExpander.cs
rename : src/Orchard/Packaging/IPackageManager.cs => src/Orchard.Web/Modules/Orchard.Packaging/Services/IPackageManager.cs
rename : src/Orchard/Packaging/IPackagingSourceManager.cs => src/Orchard.Web/Modules/Orchard.Packaging/Services/IPackagingSourceManager.cs
rename : src/Orchard/Packaging/PackageBuilder.cs => src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageBuilder.cs
rename : src/Orchard/Packaging/PackageData.cs => src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageData.cs
rename : src/Orchard/Packaging/PackageExpander.cs => src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageExpander.cs
rename : src/Orchard/Packaging/PackageManager.cs => src/Orchard.Web/Modules/Orchard.Packaging/Services/PackageManager.cs
rename : src/Orchard/Packaging/PackagingEntry.cs => src/Orchard.Web/Modules/Orchard.Packaging/Services/PackagingEntry.cs
rename : src/Orchard/Packaging/PackagingSource.cs => src/Orchard.Web/Modules/Orchard.Packaging/Services/PackagingSource.cs
rename : src/Orchard/Packaging/PackagingSourceManager.cs => src/Orchard.Web/Modules/Orchard.Packaging/Services/PackagingSourceManager.cs
rename : src/Orchard.Web/Modules/Futures.Modules.Packaging/ViewModels/PackagingHarvestViewModel.cs => src/Orchard.Web/Modules/Orchard.Packaging/ViewModels/PackagingHarvestViewModel.cs
rename : src/Orchard.Web/Modules/Futures.Modules.Packaging/ViewModels/PackagingModulesViewModel.cs => src/Orchard.Web/Modules/Orchard.Packaging/ViewModels/PackagingModulesViewModel.cs
rename : src/Orchard.Web/Modules/Futures.Modules.Packaging/ViewModels/PackagingSourcesViewModel.cs => src/Orchard.Web/Modules/Orchard.Packaging/ViewModels/PackagingSourcesViewModel.cs
rename : src/Orchard.Web/Modules/Futures.Modules.Packaging/Views/Packaging/Harvest.ascx => src/Orchard.Web/Modules/Orchard.Packaging/Views/Packaging/Harvest.ascx
rename : src/Orchard.Web/Modules/Futures.Modules.Packaging/Views/Packaging/Modules.ascx => src/Orchard.Web/Modules/Orchard.Packaging/Views/Packaging/Modules.ascx
rename : src/Orchard.Web/Modules/Futures.Modules.Packaging/Views/Packaging/Sources.ascx => src/Orchard.Web/Modules/Orchard.Packaging/Views/Packaging/Sources.ascx
rename : src/Orchard.Web/Modules/Futures.Modules.Packaging/Views/Packaging/_Subnav.ascx => src/Orchard.Web/Modules/Orchard.Packaging/Views/Packaging/_Subnav.ascx
rename : src/Orchard.Web/Modules/Futures.Modules.Packaging/Views/Web.config => src/Orchard.Web/Modules/Orchard.Packaging/Views/Web.config
rename : src/Orchard.Web/Modules/Futures.Modules.Packaging/Web.config => src/Orchard.Web/Modules/Orchard.Packaging/Web.config
This commit is contained in:
Renaud Paquay
2010-07-22 22:09:34 -07:00
parent d83f3d1520
commit b46a2944ae
36 changed files with 260 additions and 203 deletions

View File

@@ -0,0 +1,18 @@
using Orchard.Environment.Extensions;
using Orchard.Localization;
using Orchard.UI.Navigation;
namespace Orchard.Packaging {
[OrchardFeature("Gallery")]
public class AdminMenu : INavigationProvider {
public Localizer T { get; set; }
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Site Configuration"), "11", menu => menu
.Add(T("Gallery"), "5.0", item => item
.Action("Index", "Packaging", new { area = "Orchard.Packaging" })));
}
}
}

View File

@@ -0,0 +1,52 @@
using System;
using System.IO;
using System.Net;
using Orchard.Commands;
using Orchard.Packaging.Services;
namespace Orchard.Packaging.Commands {
public class GalleryCommands : DefaultOrchardCommandHandler {
private readonly IPackageManager _packageManager;
public GalleryCommands(IPackageManager packageManager) {
_packageManager = packageManager;
}
[CommandHelp("harvest <moduleName>\r\n\t" + "Package a module into a distributable")]
[CommandName("harvest")]
public void PackageCreate(string moduleName) {
var packageData = _packageManager.Harvest(moduleName);
if (packageData.PackageStream.CanSeek)
packageData.PackageStream.Seek(0, SeekOrigin.Begin);
const int chunk = 512;
var dataBuffer = new byte[3 * chunk];
var charBuffer = new char[4 * chunk + 2];
for (; ; ) {
var dataCount = packageData.PackageStream.Read(dataBuffer, 0, dataBuffer.Length);
if (dataCount <= 0)
return;
var charCount = Convert.ToBase64CharArray(dataBuffer, 0, dataCount, charBuffer, 0);
Context.Output.Write(charBuffer, 0, charCount);
}
}
[CommandHelp("harvest post <moduleName> <feedUrl>\r\n\t" + "Package a module into a distributable and push it to a feed server.")]
[CommandName("harvest post")]
public void PackageCreate(string moduleName, string feedUrl) {
var packageData = _packageManager.Harvest(moduleName);
_packageManager.Push(packageData, feedUrl);
try {
_packageManager.Push(packageData, feedUrl);
Context.Output.WriteLine("Success");
}
catch (WebException webException) {
var text = new StreamReader(webException.Response.GetResponseStream()).ReadToEnd();
throw new ApplicationException(text);
}
}
}
}

View File

@@ -0,0 +1,55 @@
using System.IO;
using Orchard.Commands;
using Orchard.Environment.Extensions;
using Orchard.Packaging.Services;
namespace Orchard.Packaging.Commands {
[OrchardFeature("Packaging")]
public class PackagingCommands : DefaultOrchardCommandHandler {
private readonly IPackageManager _packageManager;
public PackagingCommands(IPackageManager packageManager) {
_packageManager = packageManager;
}
[OrchardSwitch]
public string Filename { get; set; }
[CommandHelp("module create package <moduleName> [/Filename:filename.zip]\r\n\t" + "Create a package for the module <moduleName>. The default filename is <moduleName>-<moduleVersion>.zip.")]
[CommandName("module create package")]
[OrchardSwitches("Filename")]
public void CreatePackage(string moduleName) {
var packageData = _packageManager.Harvest(moduleName);
if (packageData == null) {
Context.Output.WriteLine(T("Module \"{0}\" does not exist in this Orchard installation.", moduleName));
return;
}
var filename = Filename;
if(string.IsNullOrEmpty(filename)) {
filename = string.Format("{0}-{1}.zip", packageData.ExtensionName, packageData.ExtensionVersion);
}
using(var stream = File.Create(filename)) {
packageData.PackageStream.CopyTo(stream);
stream.Close();
}
var fileInfo = new FileInfo(filename);
Context.Output.WriteLine(T("Package \"{0}\" successfully created", fileInfo.FullName));
}
[CommandHelp("module install package <filename>\r\n\t" + "Install a module from a package <filename>.")]
[CommandName("module install package")]
public void InstallPackage(string filename) {
if (!File.Exists(filename)) {
Context.Output.WriteLine(T("File \"{0}\" does not exist.", filename));
}
using (var stream = File.Open(filename, FileMode.Open, FileAccess.Read)) {
var packageInfo = _packageManager.Install(stream);
Context.Output.WriteLine(T("Package \"{0}\" successfully installed at \"{1}\"", packageInfo.ExtensionName, packageInfo.ExtensionPath));
}
}
}
}

View File

@@ -0,0 +1,23 @@
using System.IO;
using System.Web.Mvc;
namespace Orchard.Packaging.Controllers {
public class DownloadStreamResult : ActionResult {
public string FileName { get; set; }
public string ContentType { get; set; }
public Stream Stream { get; set; }
public DownloadStreamResult(string fileName, string contentType, Stream stream) {
FileName = fileName;
ContentType = contentType;
Stream = stream;
}
public override void ExecuteResult(ControllerContext context) {
context.HttpContext.Response.ContentType = ContentType;
context.HttpContext.Response.AddHeader("content-disposition", "attachment; filename=\"" + FileName + "\"");
Stream.Seek(0, SeekOrigin.Begin);
Stream.CopyTo(context.HttpContext.Response.OutputStream);
}
}
}

View File

@@ -0,0 +1,107 @@
using System;
using System.Linq;
using System.Web.Mvc;
using Orchard.Environment.Extensions;
using Orchard.Localization;
using Orchard.Packaging.Services;
using Orchard.Packaging.ViewModels;
using Orchard.Themes;
using Orchard.UI.Admin;
using Orchard.UI.Notify;
namespace Orchard.Packaging.Controllers {
[OrchardFeature("Gallery")]
[Themed, Admin]
public class PackagingController : Controller {
private readonly IPackageManager _packageManager;
private readonly IPackagingSourceManager _packagingSourceManager;
private readonly IExtensionManager _extensionManager;
private readonly INotifier _notifier;
public PackagingController(
IPackageManager packageManager,
IPackagingSourceManager packagingSourceManager,
IExtensionManager extensionManager,
INotifier notifier) {
_packageManager = packageManager;
_packagingSourceManager = packagingSourceManager;
_extensionManager = extensionManager;
_notifier = notifier;
T = NullLocalizer.Instance;
}
Localizer T { get; set; }
public ActionResult Index() {
return Modules();
}
public ActionResult Sources() {
return View("Sources", new PackagingSourcesViewModel {
Sources = _packagingSourceManager.GetSources(),
});
}
public ActionResult AddSource(string url) {
_packagingSourceManager.AddSource(new PackagingSource { Id = Guid.NewGuid(), FeedUrl = url });
Update();
return RedirectToAction("Sources");
}
public ActionResult Modules() {
return View("Modules", new PackagingModulesViewModel {
Modules = _packagingSourceManager.GetModuleList()
});
}
public ActionResult Update() {
_packagingSourceManager.UpdateLists();
_notifier.Information(T("List of available modules and themes is updated."));
return RedirectToAction("Index");
}
public ActionResult Harvest(string extensionName, string feedUrl) {
return View("Harvest", new PackagingHarvestViewModel {
ExtensionName = extensionName,
FeedUrl = feedUrl,
Sources = _packagingSourceManager.GetSources(),
Extensions = _extensionManager.AvailableExtensions()
});
}
[HttpPost]
public ActionResult Harvest(PackagingHarvestViewModel model) {
model.Sources = _packagingSourceManager.GetSources();
model.Extensions = _extensionManager.AvailableExtensions();
var packageData = _packageManager.Harvest(model.ExtensionName);
if (string.IsNullOrEmpty(model.FeedUrl)) {
return new DownloadStreamResult(
packageData.ExtensionName + "-" + packageData.ExtensionVersion + ".zip",
"application/x-package",
packageData.PackageStream);
}
if (!model.Sources.Any(src => src.FeedUrl == model.FeedUrl)) {
ModelState.AddModelError("FeedUrl", T("May only push directly to one of the configured sources.").ToString());
return View("Harvest", model);
}
_packageManager.Push(packageData, model.FeedUrl);
_notifier.Information(T("Harvested {0} and published onto {1}", model.ExtensionName, model.FeedUrl));
Update();
return RedirectToAction("Harvest", new { model.ExtensionName, model.FeedUrl });
}
public ActionResult Install(string syndicationId) {
var packageData = _packageManager.Download(syndicationId);
_packageManager.Install(packageData.PackageStream);
_notifier.Information(T("Installed module"));
return RedirectToAction("Modules");
}
}
}

View File

@@ -0,0 +1,19 @@
name: Packaging
antiforgery: enabled
author: The Orchard Team
website: http://orchardproject.net
version: 0.5.0
orchardversion: 0.5.0
description: The packaging module enables packaging modules using the OPC format.
features:
PackagingServices:
Description: Core services for packaging using the OPC format.
Category: Core
Orchard.Packaging:
Description: Commands for creating/installing local modules.
Dependencies: PackagingServices
Category: Packaging
Gallery:
Description: Module gallery management.
Dependencies: PackagingServices
Category: Packaging

View File

@@ -0,0 +1,141 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>
</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{DFD137A2-DDB5-4D22-BE0D-FA9AD4C8B059}</ProjectGuid>
<ProjectTypeGuids>{F85E285D-A4E0-4152-9332-AB1D724D3325};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Orchard.Packaging</RootNamespace>
<AssemblyName>Orchard.Packaging</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<MvcBuildViews>false</MvcBuildViews>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Web.DynamicData" />
<Reference Include="System.Web.Entity" />
<Reference Include="System.Web.ApplicationServices" />
<Reference Include="System.ComponentModel.DataAnnotations">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Web" />
<Reference Include="System.Web.Extensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Web.Abstractions" />
<Reference Include="System.Web.Routing" />
<Reference Include="System.Xml" />
<Reference Include="System.Configuration" />
<Reference Include="System.Web.Services" />
<Reference Include="System.EnterpriseServices" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="AdminMenu.cs" />
<Compile Include="Commands\GalleryCommands.cs" />
<Compile Include="Commands\PackagingCommands.cs" />
<Compile Include="Controllers\DownloadStreamResult.cs" />
<Compile Include="Controllers\PackagingController.cs" />
<Compile Include="Services\AtomExtensions.cs" />
<Compile Include="Services\IPackageBuilder.cs" />
<Compile Include="Services\IPackageExpander.cs" />
<Compile Include="Services\IPackageManager.cs" />
<Compile Include="Services\IPackagingSourceManager.cs" />
<Compile Include="Services\PackageBuilder.cs" />
<Compile Include="Services\PackageData.cs" />
<Compile Include="Services\PackageExpander.cs" />
<Compile Include="Services\PackageManager.cs" />
<Compile Include="Services\PackagingEntry.cs" />
<Compile Include="Services\PackagingSource.cs" />
<Compile Include="Services\PackagingSourceManager.cs" />
<Compile Include="ViewModels\PackagingHarvestViewModel.cs" />
<Compile Include="ViewModels\PackagingModulesViewModel.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ViewModels\PackagingSourcesViewModel.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Module.txt" />
<Content Include="Views\Packaging\Harvest.ascx" />
<Content Include="Views\Packaging\Modules.ascx" />
<Content Include="Views\Packaging\Sources.ascx" />
<Content Include="Views\Packaging\_Subnav.ascx" />
<Content Include="Views\Web.config" />
</ItemGroup>
<ItemGroup>
<Folder Include="Content\" />
<Folder Include="Models\" />
<Folder Include="Scripts\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Orchard\Orchard.Framework.csproj">
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>
<Name>Orchard.Framework</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="Web.config" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target> -->
<Target Name="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(ProjectDir)" />
</Target>
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>False</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>40980</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>
</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>True</UseCustomServer>
<CustomServerUrl>http://orchard.codeplex.com</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
</Project>

View File

@@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Orchard.Packaging")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Orchard")]
[assembly: AssemblyCopyright("Copyright © CodePlex Foundation 2009")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("f483c19e-56fd-442f-89fe-efed8153dbb0")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("0.5.0")]
[assembly: AssemblyFileVersion("0.5.0")]

View File

@@ -0,0 +1,16 @@
using System.Xml.Linq;
using Orchard.Environment.Extensions;
namespace Orchard.Packaging.Services {
[OrchardFeature("PackagingServices")]
internal static class AtomExtensions {
public static string Atom(this XElement entry, string localName) {
XElement element = entry.Element(AtomXName(localName));
return element != null ? element.Value : null;
}
public static XName AtomXName(string localName) {
return XName.Get(localName, "http://www.w3.org/2005/Atom");
}
}
}

View File

@@ -0,0 +1,9 @@
using System.IO;
using Orchard.Environment.Extensions;
using Orchard.Environment.Extensions.Models;
namespace Orchard.Packaging.Services {
public interface IPackageBuilder : IDependency {
Stream BuildPackage(ExtensionDescriptor extensionDescriptor);
}
}

View File

@@ -0,0 +1,15 @@
using System.IO;
using Orchard.Environment.Extensions;
namespace Orchard.Packaging.Services {
public class PackageInfo {
public string ExtensionName { get; set; }
public string ExtensionVersion { get; set; }
public string ExtensionType { get; set; }
public string ExtensionPath { get; set; }
}
public interface IPackageExpander : IDependency {
PackageInfo ExpandPackage(Stream packageStream);
}
}

View File

@@ -0,0 +1,11 @@
using System.IO;
namespace Orchard.Packaging.Services {
public interface IPackageManager : IDependency {
PackageData Harvest(string extensionName);
PackageData Download(string feedItemId);
void Push(PackageData packageData, string feedUrl);
PackageInfo Install(Stream packageStream);
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
namespace Orchard.Packaging.Services {
public interface IPackagingSourceManager : IDependency {
IEnumerable<PackagingSource> GetSources();
void AddSource(PackagingSource source);
void RemoveSource(Guid id);
void UpdateLists();
IEnumerable<PackagingEntry> GetModuleList();
}
}

View File

@@ -0,0 +1,166 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Packaging;
using System.Linq;
using System.Net.Mime;
using System.Reflection;
using System.Xml.Linq;
using Orchard.Environment.Extensions;
using Orchard.Environment.Extensions.Models;
using Orchard.FileSystems.WebSite;
namespace Orchard.Packaging.Services {
[OrchardFeature("PackagingServices")]
public class PackageBuilder : IPackageBuilder {
private readonly IExtensionManager _extensionManager;
private readonly IWebSiteFolder _webSiteFolder;
public PackageBuilder(IExtensionManager extensionManager, IWebSiteFolder webSiteFolder) {
_extensionManager = extensionManager;
_webSiteFolder = webSiteFolder;
}
#region IPackageBuilder Members
public Stream BuildPackage(ExtensionDescriptor extensionDescriptor) {
var context = new CreateContext();
BeginPackage(context);
try {
EstablishPaths(context, _webSiteFolder, extensionDescriptor.Location, extensionDescriptor.Name);
SetCoreProperties(context, extensionDescriptor);
string projectFile = extensionDescriptor.Name + ".csproj";
if (LoadProject(context, projectFile)) {
EmbedVirtualFile(context, projectFile, MediaTypeNames.Text.Xml);
EmbedProjectFiles(context, "Compile", "Content", "None", "EmbeddedResource");
EmbedReferenceFiles(context);
}
}
finally {
EndPackage(context);
}
if (context.Stream.CanSeek) {
context.Stream.Seek(0, SeekOrigin.Begin);
}
return context.Stream;
}
#endregion
private void SetCoreProperties(CreateContext context, ExtensionDescriptor extensionDescriptor) {
PackageProperties properties = context.Package.PackageProperties;
properties.Title = extensionDescriptor.DisplayName ?? extensionDescriptor.Name;
//properties.Subject = "";
properties.Creator = extensionDescriptor.Author;
properties.Keywords = extensionDescriptor.Tags;
properties.Description = extensionDescriptor.Description;
//properties.LastModifiedBy = "";
//properties.Revision = "";
//properties.LastPrinted = "";
//properties.Created = "";
//properties.Modified = "";
properties.Category = extensionDescriptor.Features.Where(f => f.Name == extensionDescriptor.Name).Select(f => f.Category).FirstOrDefault();
properties.Identifier = extensionDescriptor.Name;
properties.ContentType = "Orchard " + extensionDescriptor.ExtensionType;
//properties.Language = "";
properties.Version = extensionDescriptor.Version;
properties.ContentStatus = "";
}
private void EmbedProjectFiles(CreateContext context, params string[] itemGroupTypes) {
IEnumerable<XElement> itemGroups = context.Project
.Elements(Ns("Project"))
.Elements(Ns("ItemGroup"));
foreach (string itemGroupType in itemGroupTypes) {
IEnumerable<string> includePaths = itemGroups
.Elements(Ns(itemGroupType))
.Attributes("Include")
.Select(x => x.Value);
foreach (string includePath in includePaths) {
EmbedVirtualFile(context, includePath, MediaTypeNames.Application.Octet);
}
}
}
private void EmbedReferenceFiles(CreateContext context) {
var entries = context.Project
.Elements(Ns("Project"))
.Elements(Ns("ItemGroup"))
.Elements(Ns("Reference"))
.Select(reference => new {
Include = reference.Attribute("Include"),
HintPath = reference.Element(Ns("HintPath"))
})
.Where(entry => entry.Include != null);
foreach (var entry in entries) {
var assemblyName = new AssemblyName(entry.Include.Value);
string hintPath = entry.HintPath != null ? entry.HintPath.Value : null;
string virtualPath = "bin/" + assemblyName.Name + ".dll";
if (context.SourceFolder.FileExists(context.SourcePath + virtualPath)) {
EmbedVirtualFile(context, virtualPath, MediaTypeNames.Application.Octet);
}
else if (hintPath != null) {}
}
}
private XName Ns(string localName) {
return XName.Get(localName, "http://schemas.microsoft.com/developer/msbuild/2003");
}
private static void BeginPackage(CreateContext context) {
context.Stream = new MemoryStream();
context.Package = Package.Open(context.Stream, FileMode.Create, FileAccess.ReadWrite);
}
private static void EstablishPaths(CreateContext context, IWebSiteFolder webSiteFolder, string locationPath, string moduleName) {
context.SourceFolder = webSiteFolder;
context.SourcePath = "~/Modules/" + moduleName + "/";
context.TargetPath = "\\" + moduleName + "\\";
}
private static bool LoadProject(CreateContext context, string relativePath) {
string virtualPath = context.SourcePath + relativePath;
if (context.SourceFolder.FileExists(virtualPath)) {
context.Project = XDocument.Parse(context.SourceFolder.ReadFile(context.SourcePath + relativePath));
return true;
}
return false;
}
private static Uri EmbedVirtualFile(CreateContext context, string relativePath, string contentType) {
Uri partUri = PackUriHelper.CreatePartUri(new Uri(context.TargetPath + relativePath, UriKind.Relative));
PackagePart packagePart = context.Package.CreatePart(partUri, contentType);
using (Stream stream = packagePart.GetStream(FileMode.Create, FileAccess.Write)) {
context.SourceFolder.CopyFileTo(context.SourcePath + relativePath, stream, true /*actualContent*/);
}
return partUri;
}
private static void EndPackage(CreateContext context) {
context.Package.Close();
}
#region Nested type: CreateContext
private class CreateContext {
public Stream Stream { get; set; }
public Package Package { get; set; }
public IWebSiteFolder SourceFolder { get; set; }
public string SourcePath { get; set; }
public string TargetPath { get; set; }
public XDocument Project { get; set; }
}
#endregion
}
}

View File

@@ -0,0 +1,10 @@
using System.IO;
namespace Orchard.Packaging.Services {
public class PackageData {
public string ExtensionName { get; set; }
public string ExtensionVersion { get; set; }
public Stream PackageStream { get; set; }
}
}

View File

@@ -0,0 +1,191 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Packaging;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
using Orchard.Environment.Extensions;
using Orchard.FileSystems.VirtualPath;
using Orchard.Localization;
namespace Orchard.Packaging.Services {
[OrchardFeature("PackagingServices")]
public class PackageExpander : IPackageExpander {
private const string ContentTypePrefix = "Orchard ";
private readonly IVirtualPathProvider _virtualPathProvider;
public PackageExpander(IVirtualPathProvider virtualPathProvider) {
_virtualPathProvider = virtualPathProvider;
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
#region IPackageExpander Members
public PackageInfo ExpandPackage(Stream packageStream) {
var context = new ExpandContext();
BeginPackage(context, packageStream);
try {
GetCoreProperties(context);
EstablishPaths(context, _virtualPathProvider);
string projectFile = context.ExtensionName + ".csproj";
if (LoadProject(context, projectFile)) {
ExtractFile(context, projectFile);
ExtractProjectFiles(context, "Compile", "Content", "None", "EmbeddedResource");
ExtractReferenceFiles(context);
}
}
finally {
EndPackage(context);
}
return new PackageInfo {
ExtensionName = context.ExtensionName,
ExtensionVersion = context.ExtensionVersion,
ExtensionType = context.ExtensionType,
ExtensionPath = context.TargetPath
};
}
#endregion
private void ExtractFile(ExpandContext context, string relativePath) {
Uri partUri = PackUriHelper.CreatePartUri(new Uri(context.SourcePath + relativePath, UriKind.Relative));
PackagePart packagePart = context.Package.GetPart(partUri);
using (Stream packageStream = packagePart.GetStream(FileMode.Open, FileAccess.Read)) {
string filePath = _virtualPathProvider.Combine(context.TargetPath, relativePath);
string folderPath = _virtualPathProvider.GetDirectoryName(filePath);
if (!_virtualPathProvider.DirectoryExists(folderPath)) {
_virtualPathProvider.CreateDirectory(folderPath);
}
using (Stream fileStream = _virtualPathProvider.CreateFile(filePath)) {
packageStream.CopyTo(fileStream);
}
}
}
private void ExtractProjectFiles(ExpandContext context, params string[] itemGroupTypes) {
IEnumerable<XElement> itemGroups = context.Project
.Elements(Ns("Project"))
.Elements(Ns("ItemGroup"));
foreach (string itemGroupType in itemGroupTypes) {
IEnumerable<string> includePaths = itemGroups
.Elements(Ns(itemGroupType))
.Attributes("Include")
.Select(x => x.Value);
foreach (string includePath in includePaths) {
ExtractFile(context, includePath);
}
}
}
private void ExtractReferenceFiles(ExpandContext context) {
var entries = context.Project
.Elements(Ns("Project"))
.Elements(Ns("ItemGroup"))
.Elements(Ns("Reference"))
.Select(reference => new {
Include = reference.Attribute("Include"),
HintPath = reference.Element(Ns("HintPath"))
})
.Where(entry => entry.Include != null);
foreach (var entry in entries) {
var assemblyName = new AssemblyName(entry.Include.Value);
string hintPath = entry.HintPath != null ? entry.HintPath.Value : null;
string virtualPath = "bin/" + assemblyName.Name + ".dll";
if (PartExists(context, virtualPath)) {
ExtractFile(context, virtualPath);
}
else if (hintPath != null) {}
}
}
private bool PartExists(ExpandContext context, string relativePath) {
Uri projectUri = PackUriHelper.CreatePartUri(new Uri(context.SourcePath + relativePath, UriKind.Relative));
return context.Package.PartExists(projectUri);
}
private XName Ns(string localName) {
return XName.Get(localName, "http://schemas.microsoft.com/developer/msbuild/2003");
}
private static bool LoadProject(ExpandContext context, string relativePath) {
Uri projectUri = PackUriHelper.CreatePartUri(new Uri(context.SourcePath + relativePath, UriKind.Relative));
if (!context.Package.PartExists(projectUri)) {
return false;
}
PackagePart part = context.Package.GetPart(projectUri);
using (Stream stream = part.GetStream(FileMode.Open, FileAccess.Read)) {
context.Project = XDocument.Load(stream);
}
return true;
}
private void BeginPackage(ExpandContext context, Stream packageStream) {
if (packageStream.CanSeek) {
context.Stream = packageStream;
}
else {
context.Stream = new MemoryStream();
packageStream.CopyTo(context.Stream);
}
context.Package = Package.Open(context.Stream, FileMode.Open, FileAccess.Read);
}
private void EndPackage(ExpandContext context) {
context.Package.Close();
}
private void GetCoreProperties(ExpandContext context) {
context.ExtensionName = context.Package.PackageProperties.Identifier;
context.ExtensionVersion = context.Package.PackageProperties.Version;
string contentType = context.Package.PackageProperties.ContentType;
if (contentType.StartsWith(ContentTypePrefix)) {
context.ExtensionType = contentType.Substring(ContentTypePrefix.Length);
}
}
private void EstablishPaths(ExpandContext context, IVirtualPathProvider virtualPathProvider) {
context.SourcePath = "\\" + context.ExtensionName + "\\";
switch (context.ExtensionType) {
case "Theme":
context.TargetPath = virtualPathProvider.Combine("~/Themes/" + context.ExtensionName);
break;
case "Module":
context.TargetPath = virtualPathProvider.Combine("~/Modules/" + context.ExtensionName);
break;
default:
throw new OrchardCoreException(T("Unknown extension type \"{0}\"", context.ExtensionType));
}
}
#region Nested type: ExpandContext
private class ExpandContext {
public Stream Stream { get; set; }
public Package Package { get; set; }
public string ExtensionName { get; set; }
public string ExtensionVersion { get; set; }
public string ExtensionType { get; set; }
public string TargetPath { get; set; }
public string SourcePath { get; set; }
public XDocument Project { get; set; }
}
#endregion
}
}

View File

@@ -0,0 +1,83 @@
using System.IO;
using System.IO.Packaging;
using System.Linq;
using System.Net;
using Orchard.Environment.Extensions;
using Orchard.Environment.Extensions.Models;
namespace Orchard.Packaging.Services {
[OrchardFeature("PackagingServices")]
public class PackageManager : IPackageManager {
private readonly IExtensionManager _extensionManager;
private readonly IPackageBuilder _packageBuilder;
private readonly IPackageExpander _packageExpander;
private readonly IPackagingSourceManager _packagingSourceManager;
public PackageManager(
IExtensionManager extensionManager,
IPackagingSourceManager packagingSourceManager,
IPackageBuilder packageBuilder,
IPackageExpander packageExpander) {
_extensionManager = extensionManager;
_packagingSourceManager = packagingSourceManager;
_packageBuilder = packageBuilder;
_packageExpander = packageExpander;
}
#region IPackageManager Members
public PackageData Harvest(string extensionName) {
ExtensionDescriptor extensionDescriptor = _extensionManager.AvailableExtensions().FirstOrDefault(x => x.Name == extensionName);
if (extensionDescriptor == null) {
return null;
}
return new PackageData {
ExtensionName = extensionDescriptor.Name,
ExtensionVersion = extensionDescriptor.Version,
PackageStream = _packageBuilder.BuildPackage(extensionDescriptor),
};
}
public void Push(PackageData packageData, string feedUrl) {
WebRequest request = WebRequest.Create(feedUrl);
request.Method = "POST";
request.ContentType = "application/x-package";
using (Stream requestStream = request.GetRequestStream()) {
packageData.PackageStream.Seek(0, SeekOrigin.Begin);
packageData.PackageStream.CopyTo(requestStream);
}
using (request.GetResponse()) {
// forces request and disposes results
}
}
public PackageData Download(string feedItemId) {
PackagingEntry entry = _packagingSourceManager.GetModuleList().Single(x => x.SyndicationItem.Id == feedItemId);
WebRequest request = WebRequest.Create(entry.PackageStreamUri);
using (WebResponse response = request.GetResponse()) {
using (Stream responseStream = response.GetResponseStream()) {
var stream = new MemoryStream();
responseStream.CopyTo(stream);
Package package = Package.Open(stream);
try {
return new PackageData {
ExtensionName = package.PackageProperties.Identifier,
ExtensionVersion = package.PackageProperties.Version,
PackageStream = stream
};
}
finally {
package.Close();
}
}
}
}
public PackageInfo Install(Stream packageStream) {
return _packageExpander.ExpandPackage(packageStream);
}
#endregion
}
}

View File

@@ -0,0 +1,10 @@
using System.ServiceModel.Syndication;
namespace Orchard.Packaging.Services {
public class PackagingEntry {
public PackagingSource Source { get; set; }
public SyndicationFeed SyndicationFeed { get; set; }
public SyndicationItem SyndicationItem { get; set; }
public string PackageStreamUri { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
using System;
namespace Orchard.Packaging.Services {
public class PackagingSource {
public Guid Id { get; set; }
public string FeedUrl { get; set; }
}
}

View File

@@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.ServiceModel.Syndication;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
using Orchard.Environment.Extensions;
using Orchard.FileSystems.AppData;
namespace Orchard.Packaging.Services {
[OrchardFeature("PackagingServices")]
public class PackagingSourceManager : IPackagingSourceManager {
private static readonly XmlSerializer _sourceSerializer = new XmlSerializer(typeof (List<PackagingSource>), new XmlRootAttribute("Sources"));
private readonly IAppDataFolder _appDataFolder;
public PackagingSourceManager(IAppDataFolder appDataFolder) {
_appDataFolder = appDataFolder;
}
#region IPackagingSourceManager Members
public IEnumerable<PackagingSource> GetSources() {
string text = _appDataFolder.ReadFile(GetSourcesPath());
if (string.IsNullOrEmpty(text)) {
return Enumerable.Empty<PackagingSource>();
}
var textReader = new StringReader(_appDataFolder.ReadFile(GetSourcesPath()));
return (IEnumerable<PackagingSource>) _sourceSerializer.Deserialize(textReader);
}
public void AddSource(PackagingSource source) {
UpdateSource(source);
SaveSources(GetSources().Concat(new[] {source}));
}
public void RemoveSource(Guid id) {
SaveSources(GetSources().Where(x => x.Id != id));
}
public void UpdateLists() {
foreach (PackagingSource source in GetSources()) {
UpdateSource(source);
}
}
public IEnumerable<PackagingEntry> GetModuleList() {
IEnumerable<PackagingEntry> packageInfos = GetSources()
.SelectMany(
source =>
Bind(ParseFeed(_appDataFolder.ReadFile(GetFeedCachePath(source))),
feed =>
feed.Items.SelectMany(
item =>
Unit(new PackagingEntry {
Source = source,
SyndicationFeed = feed,
SyndicationItem = item,
PackageStreamUri = item.Links.Single().GetAbsoluteUri().AbsoluteUri,
}))));
return packageInfos.ToArray();
}
#endregion
private static string GetSourcesPath() {
return ".Packaging/Sources.xml";
}
private static string GetFeedCachePath(PackagingSource source) {
return ".Packaging/Feed." + source.Id.ToString("n") + ".xml";
}
private void SaveSources(IEnumerable<PackagingSource> sources) {
var textWriter = new StringWriter();
_sourceSerializer.Serialize(textWriter, sources.ToList());
_appDataFolder.CreateFile(GetSourcesPath(), textWriter.ToString());
}
private void UpdateSource(PackagingSource source) {
XDocument feed = XDocument.Load(source.FeedUrl, LoadOptions.PreserveWhitespace);
_appDataFolder.CreateFile(GetFeedCachePath(source), feed.ToString(SaveOptions.DisableFormatting));
}
private static XName Atom(string localName) {
return AtomExtensions.AtomXName(localName);
}
private static IEnumerable<T> Unit<T>(T t) where T : class {
return t != null ? new[] {t} : Enumerable.Empty<T>();
}
private static IEnumerable<T2> Bind<T, T2>(T t, Func<T, IEnumerable<T2>> f) where T : class {
return Unit(t).SelectMany(f);
}
private SyndicationFeed ParseFeed(string content) {
var formatter = new Atom10FeedFormatter<SyndicationFeed>();
formatter.ReadFrom(XmlReader.Create(new StringReader(content)));
return formatter.Feed;
}
}
}

View File

@@ -0,0 +1,16 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Orchard.Environment.Extensions.Models;
using Orchard.Packaging.Services;
namespace Orchard.Packaging.ViewModels {
public class PackagingHarvestViewModel {
public IEnumerable<PackagingSource> Sources { get; set; }
public IEnumerable<ExtensionDescriptor> Extensions { get; set; }
[Required]
public string ExtensionName { get; set; }
public string FeedUrl { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
using System.Collections.Generic;
using Orchard.Packaging.Services;
namespace Orchard.Packaging.ViewModels {
public class PackagingModulesViewModel {
public IEnumerable<PackagingEntry> Modules { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
using System.Collections.Generic;
using Orchard.Packaging.Services;
namespace Orchard.Packaging.ViewModels {
public class PackagingSourcesViewModel {
public IEnumerable<PackagingSource> Sources { get; set; }
}
}

View File

@@ -0,0 +1,28 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.Packaging.ViewModels.PackagingHarvestViewModel>" %>
<h1>
<%: Html.TitleForPage(T("Packaging").ToString(), T("Harvest Packages").ToString())%></h1>
<%: Html.Partial("_Subnav") %>
<%using (Html.BeginFormAntiForgeryPost()) {%>
<%: Html.ValidationSummary(T("Package creation was unsuccessful. Please correct the errors and try again.").ToString()) %>
<%foreach (var group in Model.Extensions.Where(x => !x.Location.StartsWith("~/Core")).GroupBy(x => x.ExtensionType)) {%>
<fieldset>
<legend>Harvest
<%:group.Key %></legend>
<ul>
<%foreach (var item in group) {%>
<li>
<label>
<%:Html.RadioButtonFor(m=>m.ExtensionName, item.Name, new Dictionary<string, object>{{"id",item.Name}}) %>
<%:item.DisplayName%></label></li><%
}%></ul>
<%} %>
<%: Html.ValidationMessageFor(m => m.ExtensionName)%>
</fieldset>
<fieldset>
<%: Html.LabelFor(m=>m.FeedUrl)%>
<%: Html.DropDownListFor(m => m.FeedUrl, new[]{new SelectListItem{Text="Download",Value=""}}.Concat( Model.Sources.Select(x => new SelectListItem { Text = "Push to " + x.FeedUrl, Value = x.FeedUrl })))%>
<%: Html.ValidationMessageFor(m=>m.FeedUrl) %>
</fieldset>
<input type="submit" value="Harvest" />
<%} %>

View File

@@ -0,0 +1,11 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.Packaging.ViewModels.PackagingModulesViewModel>" %>
<h1>
<%: Html.TitleForPage(T("Packaging").ToString(), T("Browse Packages").ToString())%></h1>
<%: Html.Partial("_Subnav") %>
<p><%:Html.ActionLink("Update List", "Update") %></p>
<ul>
<%foreach (var item in Model.Modules) {%><li><a href="<%:item.PackageStreamUri%>">
<%:item.SyndicationItem.Title.Text%></a> [<%:Html.ActionLink("Install", "Install", new RouteValueDictionary {{"SyndicationId",item.SyndicationItem.Id}})%>]
</li><%
}%></ul>

View File

@@ -0,0 +1,14 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.Packaging.ViewModels.PackagingSourcesViewModel>" %>
<h1>
<%: Html.TitleForPage(T("Packaging").ToString(), T("Edit Sources").ToString())%></h1>
<%: Html.Partial("_Subnav") %>
<ul>
<%foreach (var item in Model.Sources) {%><li>
<%:Html.Link(item.FeedUrl, item.FeedUrl)%></li><%
}%></ul>
<%using (Html.BeginFormAntiForgeryPost(Url.Action("AddSource"))) {%>
Url:
<%:Html.TextBox("url") %>
<input type="submit" value="Add Source" />
<%} %>

View File

@@ -0,0 +1,8 @@
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<p>
<%:Html.ActionLink("Browse Repository Packages", "Index") %>
&bull;
<%:Html.ActionLink("Harvest Local Packages", "Harvest") %>
&bull;
<%:Html.ActionLink("Edit Repository Sources", "Sources") %>
</p>

View File

@@ -0,0 +1,35 @@
<?xml version="1.0"?>
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*" type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
Enabling request validation in view pages would cause validation to occur
after the input has already been processed by the controller. By default
MVC performs request validation before a controller processes the input.
To change this behavior apply the ValidateInputAttribute to a
controller or action.
-->
<pages
validateRequest="false"
pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<controls>
<add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
</controls>
</pages>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
</handlers>
</system.webServer>
</configuration>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
</assemblies>
</compilation>
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">
<namespaces>
<add namespace="System.Web.Mvc"/>
<add namespace="System.Web.Mvc.Ajax"/>
<add namespace="System.Web.Mvc.Html"/>
<add namespace="System.Web.Routing"/>
<add namespace="System.Linq"/>
<add namespace="System.Collections.Generic"/>
<add namespace="Orchard.Mvc.Html"/>
</namespaces>
</pages>
</system.web>
<system.web.extensions/>
</configuration>