Including Orchard.CustomForms

--HG--
branch : 1.x
This commit is contained in:
Sebastien Ros
2012-08-22 15:36:04 -07:00
parent e1d6a6cad4
commit e41c207758
30 changed files with 1349 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
using Orchard.Localization;
using Orchard.Security;
using Orchard.UI.Navigation;
namespace Orchard.CustomForms {
public class AdminMenu : INavigationProvider {
public Localizer T { get; set; }
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Forms"), "4",
menu => menu
.Add(T("Manage Forms"), "1.0",
item => item.Action("Index", "Admin", new { area = "Orchard.CustomForms" }).Permission(StandardPermissions.SiteOwner))
);
}
}
}

View File

@@ -0,0 +1,145 @@
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using Orchard.ContentManagement;
using Orchard.Core.Common.Models;
using Orchard.Core.Title.Models;
using Orchard.CustomForms.Models;
using Orchard.CustomForms.ViewModels;
using Orchard.DisplayManagement;
using Orchard.Localization;
using Orchard.Security;
using System;
using Orchard.Settings;
using Orchard.UI.Navigation;
namespace Orchard.CustomForms.Controllers {
[ValidateInput(false)]
public class AdminController : Controller {
private readonly ISiteService _siteService;
public AdminController(
IOrchardServices services,
IShapeFactory shapeFactory,
ISiteService siteService) {
_siteService = siteService;
Services = services;
T = NullLocalizer.Instance;
Shape = shapeFactory;
}
dynamic Shape { get; set; }
public IOrchardServices Services { get; set; }
public Localizer T { get; set; }
public ActionResult Index(CustomFormIndexOptions options, PagerParameters pagerParameters) {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to list custom forms")))
return new HttpUnauthorizedResult();
var pager = new Pager(_siteService.GetSiteSettings(), pagerParameters);
// default options
if (options == null)
options = new CustomFormIndexOptions();
var query = Services.ContentManager.Query().ForType("CustomForm", "CustomFormWidget");
switch (options.Filter) {
case CustomFormFilter.All:
break;
}
var pagerShape = Shape.Pager(pager).TotalItemCount(query.Count());
switch (options.Order) {
case CustomFormOrder.Creation:
query = query.Join<CommonPartRecord>().OrderByDescending(u => u.CreatedUtc);
break;
}
var results = query
.Slice(pager.GetStartIndex(), pager.PageSize);
var model = new CustomFormIndexViewModel {
CustomForms = results.Select(x => new CustomFormEntry { CustomForm = x.As<CustomFormPart>() }).ToList(),
Options = options,
Pager = pagerShape
};
// maintain previous route data when generating page links
var routeData = new RouteData();
routeData.Values.Add("Options.Filter", options.Filter);
routeData.Values.Add("Options.Search", options.Search);
routeData.Values.Add("Options.Order", options.Order);
pagerShape.RouteData(routeData);
return View(model);
}
[HttpPost]
[Core.Contents.Controllers.FormValueRequired("submit.BulkEdit")]
public ActionResult Index(FormCollection input) {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage customForm")))
return new HttpUnauthorizedResult();
var viewModel = new CustomFormIndexViewModel { CustomForms = new List<CustomFormEntry>(), Options = new CustomFormIndexOptions() };
UpdateModel(viewModel);
var checkedEntries = viewModel.CustomForms.Where(c => c.IsChecked);
switch (viewModel.Options.BulkAction) {
case CustomFormBulkAction.None:
break;
case CustomFormBulkAction.Publish:
foreach (var entry in checkedEntries) {
Services.ContentManager.Publish(Services.ContentManager.Get(entry.CustomForm.Id));
}
break;
case CustomFormBulkAction.Unpublish:
foreach (var entry in checkedEntries) {
Services.ContentManager.Unpublish(Services.ContentManager.Get(entry.CustomForm.Id));
}
break;
case CustomFormBulkAction.Delete:
foreach (var entry in checkedEntries) {
Services.ContentManager.Remove(Services.ContentManager.Get(entry.CustomForm.Id));
}
break;
}
return Index(viewModel.Options, new PagerParameters());
}
public ActionResult Item(int id, PagerParameters pagerParameters) {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage customForm")))
return new HttpUnauthorizedResult();
Pager pager = new Pager(_siteService.GetSiteSettings(), pagerParameters);
var formPart = Services.ContentManager.Get(id, VersionOptions.Published).As<CustomFormPart>();
if (formPart == null)
return HttpNotFound();
var submissions = Services.ContentManager
.Query<CommonPart, CommonPartRecord>()
.ForVersion(VersionOptions.Latest)
.Where(x => x.Container.Id == id)
.OrderByDescending(x => x.CreatedUtc)
.Slice(pager.GetStartIndex(), pager.PageSize)
.Select(b => Services.ContentManager.BuildDisplay(b, "SummaryAdmin"));
var shape = Services.New.CustomFormList();
var list = Shape.List();
list.AddRange(submissions);
var totalItemCount = Services.ContentManager
.Query<CommonPart, CommonPartRecord>().Where(x => x.Container == formPart.ContentItem.Record).Count();
shape.Pager(Services.New.Pager(pager).TotalItemCount(totalItemCount));
shape.List(list);
return View(shape);
}
}
}

View File

@@ -0,0 +1,183 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.Core.Contents.Settings;
using Orchard.CustomForms.Models;
using Orchard.CustomForms.Rules;
using Orchard.Data;
using Orchard.DisplayManagement;
using Orchard.Localization;
using Orchard.Logging;
using Orchard.Mvc.Extensions;
using Orchard.Themes;
using Orchard.Tokens;
using Orchard.UI.Notify;
namespace Orchard.CustomForms.Controllers {
[Themed(true)]
public class ItemController : Controller, IUpdateModel {
private readonly IContentManager _contentManager;
private readonly ITransactionManager _transactionManager;
private readonly IRulesManager _rulesManager;
private readonly ITokenizer _tokenizer;
public ItemController(
IOrchardServices orchardServices,
IContentManager contentManager,
ITransactionManager transactionManager,
IShapeFactory shapeFactory,
IRulesManager rulesManager,
ITokenizer tokenizer) {
Services = orchardServices;
_contentManager = contentManager;
_transactionManager = transactionManager;
_rulesManager = rulesManager;
_tokenizer = tokenizer;
T = NullLocalizer.Instance;
Logger = NullLogger.Instance;
Shape = shapeFactory;
}
dynamic Shape { get; set; }
public IOrchardServices Services { get; private set; }
public Localizer T { get; set; }
public ILogger Logger { get; set; }
public ActionResult Create(int id) {
var form = _contentManager.Get(id);
if(form == null || !form.Has<CustomFormPart>()) {
return HttpNotFound();
}
var customForm = form.As<CustomFormPart>();
var contentItem = _contentManager.New(customForm.ContentType);
if(!contentItem.Has<ICommonPart>()) {
throw new OrchardException(T("The content type must have CommonPart attached"));
}
if (!Services.Authorizer.Authorize(Permissions.CreateSubmitPermission(customForm.ContentType), contentItem, T("Cannot create content")))
return new HttpUnauthorizedResult();
dynamic model = _contentManager.BuildEditor(contentItem);
model
.ContenItem(form)
.ReturnUrl(Url.RouteUrl(_contentManager.GetItemMetadata(form).DisplayRouteValues));
// Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
return View((object)model);
}
[HttpPost, ActionName("Create")]
[FormValueRequired("submit.Save")]
public ActionResult CreatePOST(int id, string returnUrl) {
return CreatePOST(id, returnUrl, contentItem => {
if (!contentItem.Has<IPublishingControlAspect>() && !contentItem.TypeDefinition.Settings.GetModel<ContentTypeSettings>().Draftable)
_contentManager.Publish(contentItem);
});
}
[HttpPost, ActionName("Create")]
[FormValueRequired("submit.Publish")]
public ActionResult CreateAndPublishPOST(int id, string returnUrl) {
var form = _contentManager.Get(id);
if (form == null || !form.Has<CustomFormPart>()) {
return HttpNotFound();
}
var customForm = form.As<CustomFormPart>();
// pass a dummy content to the authorization check to check for "own" variations
var dummyContent = _contentManager.New(customForm.ContentType);
if (!Services.Authorizer.Authorize(Permissions.CreateSubmitPermission(customForm.ContentType), dummyContent, T("Couldn't create content")))
return new HttpUnauthorizedResult();
return CreatePOST(id, returnUrl, contentItem => _contentManager.Publish(contentItem));
}
private ActionResult CreatePOST(int id, string returnUrl, Action<ContentItem> conditionallyPublish) {
var form = _contentManager.Get(id);
if (form == null || !form.Has<CustomFormPart>()) {
return HttpNotFound();
}
var customForm = form.As<CustomFormPart>();
var contentItem = _contentManager.New(customForm.ContentType);
if (!Services.Authorizer.Authorize(Permissions.CreateSubmitPermission(customForm.ContentType), contentItem, T("Couldn't create content")))
return new HttpUnauthorizedResult();
_contentManager.Create(contentItem, VersionOptions.Draft);
dynamic model = _contentManager.UpdateEditor(contentItem, this);
if (!ModelState.IsValid) {
_transactionManager.Cancel();
// if custom form is inside a widget, we display the form itself
if (form.ContentType == "CustomFormWidget") {}
// Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
return View((object)model);
}
contentItem.As<ICommonPart>().Container = customForm.ContentItem;
// triggers any event
_rulesManager.TriggerEvent("CustomForm", "Submitted",
() => new Dictionary<string, object> { { "Content", contentItem } });
if (customForm.Redirect) {
returnUrl = _tokenizer.Replace(customForm.RedirectUrl, new Dictionary<string, object> { { "Content", contentItem } });
}
// save the submitted form
if (!customForm.SaveContentItem) {
Services.ContentManager.Remove(contentItem);
}
else {
conditionallyPublish(contentItem);
}
// writes a confirmation message
if (customForm.CustomMessage) {
if (!String.IsNullOrWhiteSpace(customForm.Message)) {
Services.Notifier.Information(T(customForm.Message));
}
}
return this.RedirectLocal(returnUrl, () => Redirect(Request.RawUrl));
}
bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) {
return TryUpdateModel(model, prefix, includeProperties, excludeProperties);
}
void IUpdateModel.AddModelError(string key, LocalizedString errorMessage) {
ModelState.AddModelError(key, errorMessage.ToString());
}
}
public class FormValueRequiredAttribute : ActionMethodSelectorAttribute {
private readonly string _submitButtonName;
public FormValueRequiredAttribute(string submitButtonName) {
_submitButtonName = submitButtonName;
}
public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) {
var value = controllerContext.HttpContext.Request.Form[_submitButtonName];
return !string.IsNullOrEmpty(value);
}
}
}

View File

@@ -0,0 +1,60 @@
using System.Linq;
using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement.MetaData;
using Orchard.CustomForms.Models;
using Orchard.CustomForms.ViewModels;
namespace Orchard.CustomForms.Drivers {
public class CustomFormPartDriver : ContentPartDriver<CustomFormPart> {
private readonly IContentDefinitionManager _contentDefinitionManager;
private readonly IOrchardServices _orchardServices;
public CustomFormPartDriver(
IContentDefinitionManager contentDefinitionManager,
IOrchardServices orchardServices) {
_contentDefinitionManager = contentDefinitionManager;
_orchardServices = orchardServices;
}
protected override DriverResult Display(CustomFormPart part, string displayType, dynamic shapeHelper) {
// this method is used by the widget to render the form when it is displayed
var contentItem = _orchardServices.ContentManager.New(part.ContentType);
if (!contentItem.Has<ICommonPart>()) {
return null;
}
return ContentShape("Parts_CustomForm_Wrapper", () => {
return shapeHelper.Parts_CustomForm_Wrapper()
.Editor(_orchardServices.ContentManager.BuildEditor(contentItem))
.ContenItem(part)
.ReturnUrl(part.Redirect ? part.RedirectUrl : _orchardServices.WorkContext.HttpContext.Request.RawUrl);
});
}
protected override DriverResult Editor(CustomFormPart part, dynamic shapeHelper) {
return ContentShape("Parts_CustomForm_Fields", () => {
var contentTypes = _contentDefinitionManager.ListTypeDefinitions().Select(x => x.Name).OrderBy(x => x);
var viewModel = new CustomFormPartEditViewModel {
ContentTypes = contentTypes,
CustomFormPart = part
};
return shapeHelper.EditorTemplate(TemplateName: "Parts.CustomForm.Fields", Model: viewModel, Prefix: Prefix);
});
}
protected override DriverResult Editor(CustomFormPart part, IUpdateModel updater, dynamic shapeHelper) {
var viewModel = new CustomFormPartEditViewModel {
CustomFormPart = part
};
updater.TryUpdateModel(viewModel, Prefix, null, null);
return Editor(part, shapeHelper);
}
}
}

View File

@@ -0,0 +1,25 @@
using System.Web.Routing;
using Orchard.CustomForms.Models;
using Orchard.Data;
using Orchard.ContentManagement.Handlers;
namespace Orchard.CustomForms.Handlers {
public class CustomFormPartHandler : ContentHandler {
public CustomFormPartHandler(IRepository<CustomFormPartRecord> customFormRepository) {
Filters.Add(StorageFilter.For(customFormRepository));
}
protected override void GetItemMetadata(GetContentItemMetadataContext context) {
if(context.ContentItem.ContentType != "CustomForm") {
return;
}
context.Metadata.DisplayRouteValues = new RouteValueDictionary {
{"Area", "Orchard.CustomForms"},
{"Controller", "Item"},
{"Action", "Create"},
{"Id", context.ContentItem.Id}
};
}
}
}

View File

@@ -0,0 +1,52 @@
using Orchard.ContentManagement.MetaData;
using Orchard.Core.Contents.Extensions;
using Orchard.Data.Migration;
namespace Orchard.CustomForms {
public class Migrations : DataMigrationImpl {
public int Create() {
ContentDefinitionManager.AlterTypeDefinition("CustomForm",
cfg => cfg
.WithPart("CommonPart")
.WithPart("TitlePart")
.WithPart("AutoroutePart", builder => builder
.WithSetting("AutorouteSettings.AllowCustomPattern", "true")
.WithSetting("AutorouteSettings.AutomaticAdjustmentOnEdit", "false")
.WithSetting("AutorouteSettings.PatternDefinitions", "[{Name:'Title', Pattern: '{Content.Slug}', Description: 'my-form'}]")
.WithSetting("AutorouteSettings.DefaultPatternIndex", "0"))
.WithPart("MenuPart")
.WithPart("CustomFormPart")
.DisplayedAs("Custom Form")
.Draftable()
);
SchemaBuilder.CreateTable("CustomFormPartRecord", table => table.ContentPartVersionRecord()
.Column<string>("ContentType", c => c.WithLength(255))
.Column<bool>("CustomMessage")
.Column<string>("Message", c => c.Unlimited())
.Column<bool>("Redirect")
.Column<string>("RedirectUrl", c => c.Unlimited())
.Column<bool>("SaveContentItem")
);
return 1;
}
public int UpdateFrom1() {
ContentDefinitionManager.AlterTypeDefinition("CustomFormWidget",
cfg => cfg
.WithPart("WidgetPart")
.WithPart("CommonPart")
.WithPart("IdentityPart")
.WithPart("CustomFormPart")
.WithSetting("Stereotype", "Widget")
);
return 2;
}
public void Uninstall() {
ContentDefinitionManager.DeleteTypeDefinition("CustomForm");
}
}
}

View File

@@ -0,0 +1,43 @@
using System.ComponentModel.DataAnnotations;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.Core.Title.Models;
namespace Orchard.CustomForms.Models {
public class CustomFormPart : ContentPart<CustomFormPartRecord> {
[Required]
public string ContentType {
get { return Record.ContentType; }
set { Record.ContentType = value; }
}
public bool SaveContentItem {
get { return Record.SaveContentItem; }
set { Record.SaveContentItem = value; }
}
public bool CustomMessage {
get { return Record.CustomMessage; }
set { Record.CustomMessage = value; }
}
public string Message {
get { return Record.Message; }
set { Record.Message = value; }
}
public bool Redirect {
get { return Record.Redirect; }
set { Record.Redirect = value; }
}
public string RedirectUrl {
get { return Record.RedirectUrl; }
set { Record.RedirectUrl = value; }
}
public string Title {
get { return this.As<ITitleAspect>().Title; }
}
}
}

View File

@@ -0,0 +1,18 @@
using System.ComponentModel.DataAnnotations;
using Orchard.ContentManagement.Records;
using Orchard.Data.Conventions;
namespace Orchard.CustomForms.Models {
public class CustomFormPartRecord : ContentPartRecord {
[StringLength(255)]
public virtual string ContentType { get; set; }
[StringLengthMax]
public virtual string Message { get; set; }
public virtual bool CustomMessage { get; set; }
public virtual bool SaveContentItem { get; set; }
[StringLengthMax]
public virtual string RedirectUrl { get; set; }
public virtual bool Redirect { get; set; }
}
}

View File

@@ -0,0 +1,13 @@
Name: Custom Forms
AntiForgery: enabled
Author: The Orchard Team
Website: http://orchardcustomforms.codeplex.com
Version: 1.5
OrchardVersion: 1.4
Description: Create custom forms like contact forms or content contributions.
Features:
Orchard.CustomForms:
Name: Custom Forms
Description: Create custom forms like contact forms or content contributions.
Category: Forms
Dependencies: Contents, Orchard.Tokens

View File

@@ -0,0 +1,177 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{2CF067CA-064B-43C6-8B88-5E3B99A65F1D}</ProjectGuid>
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Orchard.CustomForms</RootNamespace>
<AssemblyName>Orchard.CustomForms</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<MvcBuildViews>false</MvcBuildViews>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>4.0</OldToolsVersion>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<TargetFrameworkProfile />
<UseIISExpress>false</UseIISExpress>
</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>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</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>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.ComponentModel.DataAnnotations">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Web.DynamicData" />
<Reference Include="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\lib\aspnetmvc\System.Web.Mvc.dll</HintPath>
</Reference>
<Reference Include="System.Web" />
<Reference Include="System.Web.Abstractions" />
<Reference Include="System.Web.Routing" />
<Reference Include="System.Xml" />
<Reference Include="System.Configuration" />
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<Content Include="Web.config" />
<Content Include="Views\Web.config" />
<Content Include="Scripts\Web.config" />
<Content Include="Styles\Web.config" />
<Content Include="Properties\AssemblyInfo.cs" />
<Content Include="Module.txt" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Orchard\Orchard.Framework.csproj">
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>
<Name>Orchard.Framework</Name>
</ProjectReference>
<ProjectReference Include="..\..\Core\Orchard.Core.csproj">
<Project>{9916839C-39FC-4CEB-A5AF-89CA7E87119F}</Project>
<Name>Orchard.Core</Name>
</ProjectReference>
<ProjectReference Include="..\Orchard.Tokens\Orchard.Tokens.csproj">
<Project>{6F759635-13D7-4E94-BCC9-80445D63F117}</Project>
<Name>Orchard.Tokens</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="AdminMenu.cs" />
<Compile Include="Controllers\AdminController.cs" />
<Compile Include="Controllers\ItemController.cs" />
<Compile Include="Drivers\CustomFormPartDriver.cs" />
<Compile Include="Permissions.cs" />
<Compile Include="Handlers\CustomFormPartHandler.cs" />
<Compile Include="Migrations.cs" />
<Compile Include="Models\CustomFormPart.cs" />
<Compile Include="Models\CustomFormPartRecord.cs" />
<Compile Include="Rules\CustomFormEvents.cs" />
<Compile Include="Rules\IRulesManager.cs" />
<Compile Include="Security\AuthorizationEventHandler.cs" />
<Compile Include="ViewModels\CustomFormIndexViewModel.cs" />
<Compile Include="ViewModels\CustomFormPartEditViewModel.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Admin\Index.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Admin\Item.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\EditorTemplates\Parts.CustomForm.Fields.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Item\Create.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Item\Edit.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Parts.CustomForm.Edit.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Parts.CustomForm.SummaryAdmin.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Placement.info">
<SubType>Designer</SubType>
</Content>
</ItemGroup>
<ItemGroup>
<Folder Include="Services\" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Parts.CustomForm.Wrapper.cshtml" />
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
<!-- 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" DependsOnTargets="AfterBuildCompiler">
<PropertyGroup>
<AreasManifestDir>$(ProjectDir)\..\Manifests</AreasManifestDir>
</PropertyGroup>
<!-- If this is an area child project, uncomment the following line:
<CreateAreaManifest AreaName="$(AssemblyName)" AreaType="Child" AreaPath="$(ProjectDir)" ManifestPath="$(AreasManifestDir)" ContentFiles="@(Content)" />
-->
<!-- If this is an area parent project, uncomment the following lines:
<CreateAreaManifest AreaName="$(AssemblyName)" AreaType="Parent" AreaPath="$(ProjectDir)" ManifestPath="$(AreasManifestDir)" ContentFiles="@(Content)" />
<CopyAreaManifests ManifestPath="$(AreasManifestDir)" CrossCopy="false" RenameViews="true" />
-->
</Target>
<Target Name="AfterBuildCompiler" Condition="'$(MvcBuildViews)'=='true'">
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(ProjectDir)\..\$(ProjectName)" />
</Target>
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>False</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>51352</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,92 @@
using System;
using System.Linq;
using System.Collections.Generic;
using Orchard.ContentManagement;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Models;
using Orchard.CustomForms.Models;
using Orchard.Environment.Extensions.Models;
using Orchard.Security.Permissions;
namespace Orchard.CustomForms {
public class Permissions : IPermissionProvider {
private static readonly Permission SubmitAnyForm = new Permission { Description = "Submit any forms", Name = "Submit" };
private static readonly Permission SubmitForm = new Permission { Description = "Submit {0} forms", Name = "Submit_{0}", ImpliedBy = new[] { SubmitAnyForm } };
private readonly IContentDefinitionManager _contentDefinitionManager;
private readonly IContentManager _contentManager;
public virtual Feature Feature { get; set; }
public Permissions(IContentDefinitionManager contentDefinitionManager, IContentManager contentManager) {
_contentDefinitionManager = contentDefinitionManager;
_contentManager = contentManager;
}
public IEnumerable<Permission> GetPermissions() {
// manage rights only for Creatable types
var formTypes = _contentManager.Query<CustomFormPart>().List().Select(x => x.ContentType).Distinct();
foreach (var contentType in formTypes) {
var typeDefinition = _contentDefinitionManager.GetTypeDefinition(contentType);
if(typeDefinition == null) {
continue;
}
yield return CreateSubmitPermission(typeDefinition);
}
yield return SubmitAnyForm;
}
public IEnumerable<PermissionStereotype> GetDefaultStereotypes() {
return new[] {
new PermissionStereotype {
Name = "Administrator",
Permissions = new[] { SubmitAnyForm }
},
new PermissionStereotype {
Name = "Editor",
Permissions = new[] { SubmitAnyForm }
},
new PermissionStereotype {
Name = "Moderator",
Permissions = new[] { SubmitAnyForm }
},
new PermissionStereotype {
Name = "Author",
Permissions = new[] { SubmitAnyForm }
},
new PermissionStereotype {
Name = "Contributor",
Permissions = new[] { SubmitAnyForm }
}
};
}
/// <summary>
/// Generates a permission dynamically for a content type
/// </summary>
public static Permission CreateSubmitPermission(ContentTypeDefinition typeDefinition) {
return new Permission {
Name = String.Format(SubmitForm.Name, typeDefinition.Name),
Description = String.Format(SubmitForm.Description, typeDefinition.DisplayName),
Category = "Custom Forms",
ImpliedBy = new [] { SubmitForm }
};
}
/// <summary>
/// Generates a permission dynamically for a content type
/// </summary>
public static Permission CreateSubmitPermission(string contentType) {
return new Permission {
Name = String.Format(SubmitForm.Name, contentType),
Description = String.Format(SubmitForm.Description, contentType),
Category = "Custom Forms",
ImpliedBy = new[] { SubmitForm }
};
}
}
}

View File

@@ -0,0 +1,4 @@
<Placement>
<Place Parts_CustomForm_Wrapper="Content:1"/>
<Place Parts_CustomForm_Fields="Content:5"/>
</Placement>

View File

@@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
// 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.CustomForms")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyProduct("Orchard")]
[assembly: AssemblyCopyright("")]
[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("e7ce3952-50fa-4887-9cf5-10ec8fd6f930")]
// 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("1.5")]
[assembly: AssemblyFileVersion("1.5")]

View File

@@ -0,0 +1,55 @@
using System;
using System.Linq;
using Orchard.ContentManagement;
using Orchard.Events;
using Orchard.Localization;
namespace Orchard.CustomForms.Rules {
public interface IEventProvider : IEventHandler {
void Describe(dynamic describe);
}
public class CustomFormEvents : IEventProvider {
public CustomFormEvents() {
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
public void Describe(dynamic describe) {
Func<dynamic, bool> contentHasPart = ContentHasPart;
describe.For("CustomForm", T("Custom Forms"), T("Custom Forms"))
.Element("Submitted", T("Custom Form Submitted"), T("Custom Form is submitted."), contentHasPart, (Func<dynamic, LocalizedString>)(context => T("When a custom form for types ({0}) is submitted.", FormatPartsList(context))), "SelectContentTypes")
;
}
private string FormatPartsList(dynamic context) {
var contenttypes = context.Properties["contenttypes"];
if (String.IsNullOrEmpty(contenttypes)) {
return T("Any").Text;
}
return contenttypes;
}
private static bool ContentHasPart(dynamic context) {
string contenttypes = context.Properties["contenttypes"];
var content = context.Tokens["Content"] as IContent;
// "" means 'any'
if (String.IsNullOrEmpty(contenttypes)) {
return true;
}
if (content == null) {
return false;
}
var contentTypes = contenttypes.Split(new[] { ',' });
return contentTypes.Any(contentType => content.ContentItem.TypeDefinition.Name == contentType);
}
}
}

View File

@@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
using Orchard.Events;
namespace Orchard.CustomForms.Rules {
public interface IRulesManager : IEventHandler {
void TriggerEvent(string category, string type, Func<Dictionary<string, object>> tokensContext);
}
}

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appSettings>
<add key="webpages:Enabled" value="false" />
</appSettings>
<system.web>
<httpHandlers>
<!-- iis6 - for any request in this location, return via managed static file handler -->
<add path="*" verb="*" type="System.Web.StaticFileHandler" />
</httpHandlers>
</system.web>
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="7.00:00:00" />
</staticContent>
<handlers accessPolicy="Script,Read">
<!--
iis7 - for any request to a file exists on disk, return it via native http module.
accessPolicy 'Script' is to allow for a managed 404 page.
-->
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" preCondition="integratedMode" resourceType="File" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>

View File

@@ -0,0 +1,26 @@
using JetBrains.Annotations;
using Orchard.ContentManagement;
using Orchard.CustomForms.Models;
using Orchard.Security;
namespace Orchard.CustomForms.Security {
/// <summary>
/// Alters the Edit permission requested by the Contents module before editing a form. Returns a Submit permission instead.
/// </summary>
[UsedImplicitly]
public class AuthorizationEventHandler : IAuthorizationServiceEventHandler {
public void Checking(CheckAccessContext context) { }
public void Complete(CheckAccessContext context) { }
public void Adjust(CheckAccessContext context) {
if (!context.Granted
&& context.Permission.Name == Orchard.Core.Contents.Permissions.EditContent.Name
&& context.Content != null
&& context.Content.ContentItem.ContentType == "CustomForm") {
context.Adjusted = true;
context.Permission = Permissions.CreateSubmitPermission(context.Content.ContentItem.As<CustomFormPart>().ContentType);
}
}
}
}

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appSettings>
<add key="webpages:Enabled" value="false" />
</appSettings>
<system.web>
<httpHandlers>
<!-- iis6 - for any request in this location, return via managed static file handler -->
<add path="*" verb="*" type="System.Web.StaticFileHandler" />
</httpHandlers>
</system.web>
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="7.00:00:00" />
</staticContent>
<handlers accessPolicy="Script,Read">
<!--
iis7 - for any request to a file exists on disk, return it via native http module.
accessPolicy 'Script' is to allow for a managed 404 page.
-->
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" preCondition="integratedMode" resourceType="File" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>

View File

@@ -0,0 +1,39 @@
using System.Collections.Generic;
using Orchard.CustomForms.Models;
namespace Orchard.CustomForms.ViewModels {
public class CustomFormIndexViewModel {
public IList<CustomFormEntry> CustomForms { get; set; }
public CustomFormIndexOptions Options { get; set; }
public dynamic Pager { get; set; }
}
public class CustomFormEntry {
public CustomFormPart CustomForm { get; set; }
public bool IsChecked { get; set; }
}
public class CustomFormIndexOptions {
public string Search { get; set; }
public CustomFormOrder Order { get; set; }
public CustomFormFilter Filter { get; set; }
public CustomFormBulkAction BulkAction { get; set; }
}
public enum CustomFormOrder {
Name,
Creation
}
public enum CustomFormFilter {
All,
}
public enum CustomFormBulkAction {
None,
Publish,
Unpublish,
Delete
}
}

View File

@@ -0,0 +1,9 @@
using System.Collections.Generic;
using Orchard.CustomForms.Models;
namespace Orchard.CustomForms.ViewModels {
public class CustomFormPartEditViewModel {
public IEnumerable<string> ContentTypes { get; set; }
public CustomFormPart CustomFormPart { get; set; }
}
}

View File

@@ -0,0 +1,81 @@
@using Orchard.CustomForms.ViewModels
@using Orchard.Utility.Extensions
@model Orchard.CustomForms.ViewModels.CustomFormIndexViewModel
@{
var formIndex = 0;
var pageSizes = new List<int?>() { 10, 50, 100 };
var defaultPageSize = WorkContext.CurrentSite.PageSize;
if(!pageSizes.Contains(defaultPageSize)) {
pageSizes.Add(defaultPageSize);
}
}
<h1>@Html.TitleForPage(T("Manage Custom Forms").ToString()) </h1>
@using (Html.BeginFormAntiForgeryPost()) {
@Html.ValidationSummary()
<div class="manage">@Html.ActionLink(T("Add a new Custom Form").ToString(), "Create", "Admin", new { area = "Contents", id = "CustomForm", returUrl = Request.RawUrl }, new { @class = "button primaryAction" })</div>
<fieldset class="bulk-actions">
<label for="publishActions">@T("Actions:")</label>
<select id="publishActions" name="@Html.NameOf(m => m.Options.BulkAction)">
@Html.SelectOption(Model.Options.BulkAction, CustomFormBulkAction.None, T("Choose action...").ToString())
@Html.SelectOption(Model.Options.BulkAction, CustomFormBulkAction.Publish, T("Publish").ToString())
@Html.SelectOption(Model.Options.BulkAction, CustomFormBulkAction.Unpublish, T("Unpublish").ToString())
@Html.SelectOption(Model.Options.BulkAction, CustomFormBulkAction.Delete, T("Delete").ToString())
</select>
<button type="submit" name="submit.BulkEdit" value="@T("Apply")">@T("Apply")</button>
</fieldset>
<fieldset class="bulk-actions">
<label for="filterResults">@T("Sort by:")</label>
<select id="filterResults" name="@Html.NameOf(m => m.Options.Order)">
@Html.SelectOption(Model.Options.Order, CustomFormOrder.Creation, T("Creation date").ToString())
</select>
<input type="hidden" name="Page" value="1" />
<label for="pageSize">@T("Show:")</label>
<select id="pageSize" name="PageSize">
@Html.SelectOption((int)Model.Pager.PageSize, 0, T("All").ToString())
@foreach(int size in pageSizes.OrderBy(p => p)) {
@Html.SelectOption((int)Model.Pager.PageSize, size, size.ToString())
}
</select>
<button type="submit" name="submit.Filter" value="@T("Filter")">@T("Filter")</button>
</fieldset>
<fieldset>
<table class="items">
<thead>
<tr>
<th scope="col">&nbsp;&darr;</th>
<th scope="col">@T("Title")</th>
<th scope="col">@T("Content Type")</th>
<th scope="col">&nbsp;</th>
</tr>
</thead>
@foreach (var entry in Model.CustomForms) {
<tr>
<td>
<input type="hidden" value="@Model.CustomForms[formIndex].CustomForm.Id" name="@Html.NameOf(m => m.CustomForms[formIndex].CustomForm.Id)"/>
<input type="checkbox" value="true" name="@Html.NameOf(m => m.CustomForms[formIndex].IsChecked)"/>
</td>
<td>
@Html.ItemEditLink(entry.CustomForm.Title, entry.CustomForm.ContentItem)
@if (entry.CustomForm.ContentItem.ContentType == "CustomFormWidget") {
@T("-")<text> </text>@T("Widget")
}
</td>
<td>
@entry.CustomForm.ContentType.CamelFriendly()
</td>
<td>
@Html.ItemEditLink(T("Edit").Text, entry.CustomForm.ContentItem) @T(" | ")
@Html.Link(T("Delete").Text, Url.ItemRemoveUrl(entry.CustomForm.ContentItem, new { returnUrl = Request.RawUrl }), new { itemprop = "RemoveUrl UnsafeUrl" }) @T(" | ")
@Html.ActionLink(T("Submissions").Text, "Item", "Admin", new { area = "Orchard.CustomForms", id = entry.CustomForm.Id }, new { })
</td>
</tr>
formIndex++;
}
</table>
@Display(Model.Pager)
</fieldset>
}

View File

@@ -0,0 +1,30 @@
@using Orchard.Core.Contents.ViewModels;
@using Orchard.Utility.Extensions;
@{
Model.List.Classes.Add("content-items");
}
@if (Model.List.Items.Count > 0) {
using (Html.BeginFormAntiForgeryPost(Url.Action("Item", "Admin", new { area = "Orchard.CustomForms", id = "" }))) {
<fieldset class="bulk-actions">
<label for="publishActions">@T("Actions:")</label>
<select id="publishActions" name="Options.BulkAction">
@Html.SelectOption(ContentsBulkAction.None, ContentsBulkAction.None, T("Choose action...").ToString())
@Html.SelectOption(ContentsBulkAction.None, ContentsBulkAction.PublishNow, T("Publish Now").ToString())
@Html.SelectOption(ContentsBulkAction.None, ContentsBulkAction.Unpublish, T("Unpublish").ToString())
@Html.SelectOption(ContentsBulkAction.None, ContentsBulkAction.Remove, T("Delete").ToString())
</select>
@Html.Hidden("returnUrl", ViewContext.RequestContext.HttpContext.Request.ToUrlString())
<button type="submit" name="submit.BulkEdit" value="yes">@T("Apply")</button>
</fieldset>
<fieldset class="contentItems bulk-items">
@Display(Model.List)
</fieldset>
}
}
else {
<div class="info message">@T("There are no submissions for this form.")</div>
}
@Display(Model.Pager)

View File

@@ -0,0 +1,43 @@
@using Orchard.Utility.Extensions
@model Orchard.CustomForms.ViewModels.CustomFormPartEditViewModel
@Display.TokenHint()
<fieldset>
<label for="@Html.FieldIdFor(m => m.CustomFormPart.ContentType)">@T("Content Type")</label>
<select id="@Html.FieldIdFor(m => m.CustomFormPart.ContentType)" name="@Html.FieldNameFor(m => m.CustomFormPart.ContentType)">
@foreach(string contentType in Model.ContentTypes) {
@Html.SelectOption(contentType, contentType.Equals(Model.CustomFormPart.ContentType, StringComparison.OrdinalIgnoreCase), contentType.CamelFriendly())
}
</select>
<span class="hint">@T("Select the content type which will be used to render the custom form.")</span>
@Html.ValidationMessageFor(m => m.CustomFormPart.ContentType)
</fieldset>
<fieldset>
@Html.EditorFor(m => m.CustomFormPart.SaveContentItem)
<label for="@Html.FieldIdFor(m => m.CustomFormPart.SaveContentItem)" class="forcheckbox">@T("Save the content item once the form is submitted")</label>
<span class="hint">@T("Check if you want to save the content item associated to the form. Leave empty if you just want to trigger an action on the event.")</span>
</fieldset>
<fieldset>
@Html.EditorFor(m => m.CustomFormPart.CustomMessage)
<label for="@Html.FieldIdFor(m => m.CustomFormPart.CustomMessage)" class="forcheckbox">@T("Specificy a custom message when the form is submitted")</label>
<div data-controllerid="@Html.FieldIdFor(m => m.CustomFormPart.CustomMessage)">
@Html.LabelFor(m => m.CustomFormPart.Message)
@Html.TextBoxFor(m => m.CustomFormPart.Message, new { @class = "text large"})
<span class="hint">@T("The custom message to display to the user when the form is submitted. Leave empty if no messages should be displayed.")</span>
</div>
</fieldset>
<fieldset>
@Html.EditorFor(m => m.CustomFormPart.Redirect)
<label for="@Html.FieldIdFor(m => m.CustomFormPart.Redirect)" class="forcheckbox">@T("Redirect the user once the form is submitted")</label>
<div data-controllerid="@Html.FieldIdFor(m => m.CustomFormPart.Redirect)">
@Html.LabelFor(m => m.CustomFormPart.RedirectUrl)
@Html.TextBoxFor(m => m.CustomFormPart.RedirectUrl, new { @class = "text large tokenized" })
<span class="hint">@T("The url the user should be redirected to once the form is successfully submitted. e.g.: ~/About")</span>
</div>
</fieldset>

View File

@@ -0,0 +1,19 @@
@using Orchard.ContentManagement
@{
ContentItem customForm = Model.ContentItem;
string returnUrl = Model.ReturnUrl;
// remove default Save/Publish buttons
Model.Zones["Sidebar"].Items.Clear();
}
@using (Html.BeginFormAntiForgeryPost(returnUrl)) {
@Html.ValidationSummary()
// Model is a Shape, calling Display() so that it is rendered using the most specific template for its Shape type
@Display(Model)
<fieldset class="submit-button">
<button type="submit" name="submit.Save" value="submit.Save">@T("Submit")</button>
</fieldset>
}

View File

@@ -0,0 +1,5 @@
@using (Html.BeginFormAntiForgeryPost()) {
@Html.ValidationSummary()
// Model is a Shape, calling Display() so that it is rendered using the most specific template for its Shape type
@Display(Model)
}

View File

@@ -0,0 +1,6 @@
@using Orchard.ContentManagement;
@using (Html.BeginFormAntiForgeryPost(Url.Action("Create", "Item", new { area = "Orchard.CustomForms", id = Model.ContentPart.ContentType }))) {
@Html.ValidationSummary()
@Display(Model.Editor)
}

View File

@@ -0,0 +1,8 @@
@using Orchard.ContentManagement;
@{
ContentItem contentItem = Model.ContentItem;
}
<div>
@T("Renders a form for {0}", Model.ContentPart.ContentType)
</div>

View File

@@ -0,0 +1,21 @@
@using Orchard.ContentManagement;
@{
ContentItem customForm = Model.ContentItem;
string returnUrl = Model.ReturnUrl;
// remove default Save/Publish buttons
Model.Editor.Zones["Sidebar"].Items.Clear();
}
@using (Html.BeginFormAntiForgeryPost(Url.Action("Create", "Item", new { area = "Orchard.CustomForms", id = Model.ContentItem.Id }))) {
@Html.ValidationSummary()
// Model is a Shape, calling Display() so that it is rendered using the most specific template for its Shape type
@Display(Model.Editor)
@Html.Hidden("returnUrl", returnUrl);
<fieldset class="submit-button">
<button type="submit" name="submit.Save" value="submit.Save">@T("Submit")</button>
</fieldset>
}

View File

@@ -0,0 +1,41 @@
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="webpages:Enabled" value="false" />
</appSettings>
<system.web>
<httpHandlers>
</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=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"
pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"
userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<controls>
<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" namespace="System.Web.Mvc" tagPrefix="mvc" />
</controls>
</pages>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
</handlers>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="2.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -0,0 +1,41 @@
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<remove name="host" />
<remove name="pages" />
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
</sectionGroup>
</configSections>
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<pages pageBaseType="Orchard.Mvc.ViewEngines.Razor.WebViewPage">
<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.Web.WebPages" />
<add namespace="System.Linq"/>
<add namespace="System.Collections.Generic"/>
<add namespace="Orchard.Mvc.Html"/>
</namespaces>
</pages>
</system.web.webPages.razor>
<system.web>
<compilation targetFramework="4.0">
<assemblies>
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add assembly="System.Data.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</assemblies>
</compilation>
</system.web>
</configuration>