GithubHelp home page GithubHelp logo

n2cms / n2cms Goto Github PK

View Code? Open in Web Editor NEW
363.0 42.0 195.0 197.98 MB

N2 CMS, an open source CMS for ASP.NET

Home Page: http://n2cms.com

License: Other

C# 77.22% Shell 0.01% Inno Setup 0.01% Pascal 0.04% ASP 4.18% CSS 4.44% HTML 2.83% Smalltalk 0.01% JavaScript 11.23% Batchfile 0.01% SQLPL 0.02%

n2cms's Introduction

New: Join the N2CMS chat on Telegram: https://t.me/joinchat/AAAAAA4oUpeYPAMOVGhGuw

Welcome to N2CMS

N2CMS is a lightweight CMS framework. With just a few strokes of your keyboard a wonderful strongly-typed model emerges complete with a management UI. You can spend the rest of your day building the best site imaginable.

It's so .NET! With N2CMS, you build the model of the data that needs to be managed using C# or VB code in Visual Studio. The type below is picked up by the N2 engine at runtime and made available to be edited. The code uses an open API with multiple built-in options and unlimited customization options.

All you have to do is design your model class (inherit N2.ContentItem) and define which properties are editable by adding attributes

// [RootPage()]  - use this if you want this page type to be a "Root page"
// [StartPage()] - use this if you want this page type to be a "Start page"
[PageDefinition(TemplateUrl = "~/my/pageitemtemplate.aspx")]
public class PageItem : N2.ContentItem
{
    [EditableFreeTextArea]
    public virtual string Text { get; set; }
}

Quick Start

For a quick start, follow these instructions, which assume that you are using ASP.NET MVC + Razor (the "Dinamico" template pack -- see below for details).

  1. Create a new, empty Web Application Project in Visual Studio 2012 or 2013.

  2. Go to Tools > Library Package Manager > Package Manager Console

  3. In the Package Manager console run the following commands:

    Install-Package N2CMS.Dinamico
    Install-Package N2CMS.Management
    
  4. Configure database, e.g. SqlLite for small sites:

    Install-Package N2CMS.Config.SQLite
    
  5. Run your Web Application Project and follow on-screen advice.

  6. A tip on selecting root and start nodes: StartPage single node is usually good enough for simple sites, RootPage and LanguageIntersection two node configuration is a good choice for multilingual sites (add localized StartPages later).

Please note, N2CMS supports the following ASP.NET view engines:

  • ASP.NET MVC + Razor ("Dinamico" template pack)
  • ASP.NET MVC + MVC Views ("MVC" template pack)
  • ASP.NET Web Forms

It is NOT ENOUGH to install just the N2CMS package. If you use the N2CMS standalone NuGet, you still need either N2CMS.Dinamico or N2CMS.MVC NuGet for it to work properly.

Detailed installation instructions are available at: https://github.com/n2cms/n2cms/blob/master/README_SETUP.md or in our documentation wiki: https://n2cmsdocs.atlassian.net/wiki/display/N2CMS/Getting+Started+using+N2CMS

For development ("bleeding edge") packages, you can add our MyGet feed to your NuGet package manager. Please follow the instructions in NuGet documentation for doing this. Here are the feed URLs:


API

You can use the API within your methods and properties to develop advanced content manageable features.

public void DoSomeStuffWithSomeItems(DateTime minDate, DateTime maxDate)
{
	IList<ContentItem> items = N2.Find.Items
		.Where.Created.Between(minDate, maxDate)
		.And.SavedBy.Eq("admin")
		.OrderBy.Published.Desc
		.Select();

	foreach (ContentItem item in items)
		DoSomethingWith(item);
}

There are more API usage examples here: http://n2cms.com/Documentation/Manipulating%20content/Finding%20content.aspx.

I want this in my project. Where do I download it?

Install the Nuget package: http://www.nuget.org/packages/N2CMS/

##Where do I get more advanced documentation?

###Reference Documentation On our Confluence wiki: https://n2cmsdocs.atlassian.net/wiki/display/N2CMS/Getting+Started+using+N2CMS

We know... we need to move this to github wiki or our public site. We are the cobblers kids. Would love help if you are interested. Contact us.

Screenshots

Management Console

Management Console

Page or Part Edit

Page / Part Edit

Examples

We currently post them on CodePlex: http://n2cms.codeplex.com/releases/. You can also find them in the source code within this repo.

You may have to make certain configuration changes when moving the code to a hosting provider. Common issues are addressed here: http://n2cms.com/wiki/Troubleshooting-site-deployment.aspx

Clone the Source Code and Contribute to N2CMS

What is here?

Here you will find the N2 CMS framework and a number of template projects that demonstrate alternative ways to use this CMS. They all share a framework that consists of N2.dll and the UI management files residing below the /N2/ folder.

How do I setup my development environment?

  1. Clone this repo to your PC.
  2. Double-click on Prepare_AllDependencies.bat
  3. Choose amount of templates (ranging from minimal example to many features in the box):
    • Examples - Minimal C#
    • Examples - Minimal Visual Basic
    • Examples - Minimal MVC
    • Src - Dinamico
    • Src - MVC Templates
    • Src - WebForm Templates
  4. Choose between N2.Everything.sln to open everything, or venture down the directory structure of Src or Examples and open a solution down there.
  5. Find the Visual Studio solution explorer find the web project you chose (2.), right-click on it and select "Set as StartUp Project".
  6. Set the a web site project as startup project (N2.Templates.* or Dinamico in src)
  7. Compile and run (Ctrl+F5)

N2 CMS supports many databases, this code is set up to use the SQLite embedded database. You may want to use SQL Server or MySQL in production.

More Resources and Documentation

Feedback

You are very welcome to let us know about your build experiences in the issues so we can continue to improve things. Pull requests are also welcomed.

Frequently Asked Questions

What does the N2 in N2CMS stand for? It is short for "en tva" (1-2 in swedish).

I want to create an open source project based on N2CMS. I want N2CMS to be part of branding my project. Do you have guidance on naming my project?

Yes, please use the entire project name "N2CMS" in your project name. For example, N2CMS.BootstrapBlog would be great project name. We feel that just using "N2" is too generic. Using N2CMS will help with organic search results.

n2cms's People

Contributors

abadiwidodo avatar alexjamesbrown avatar andpoulsen avatar andy4711 avatar andypatterson avatar bherila avatar bratn avatar carlraymond avatar christianfredh avatar dejanmilicic avatar eugene-zen avatar faester avatar grimaceofdespair avatar janpub avatar jronaldi avatar jsassner avatar kodeo avatar laurachan avatar libardo avatar lpodolak avatar markthiessen avatar meixger avatar nazjunaid avatar nimore avatar schourode avatar sntsdev avatar tazer avatar tonimontana avatar vkornov avatar wrohrbach avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

n2cms's Issues

N2.Web.Link.To should htmlencode ampersands

...because they are understood as broken html entities otherwise.

To put it more precisely:
N2.Web.Link.To(item).AddQuery("foo", 1).AddQuery("bar", 2)
generates a link with attribute href="/path/to/item?foo=1&bar=2"
while it should really be href="/path/to/item?foo=1&bar=2"

http://htmlhelp.com/tools/validator/problems.html#amp
http://www.htmlpedia.org/wiki/Sp_325

The standard MVC helper does it nicely:
Html.ActionLink(c => c.SomeAction(1, 2), "do it!")
comments

stevencouk wrote Nov 12, 2009 at 3:06 AM

As the N2.Templates.Web.UI.WebControls.Menu control uses N2.Web.Link.To, it means the links generated in the this are not html encoded as well.
stefanb wrote Mar 15, 2010 at 3:54 AM

this breaks all xhtml pages with such links in Opera, which uses less forgiving XHTML validation with error message:

XML parsing failed

XML parsing failed: syntax error (Line: 276, Character: 84)

Reparse document as HTML
Error:
invalid entity reference in attribute value

Specification:
http://www.w3.org/TR/REC-xml/

Wrong date format

See this discussion http://n2cms.codeplex.com/discussions/277260

*Just installed dinamico to empty mvc 3 project. Date picker for publish date writes wrong value to the input box: seems to have year written twice.

Edit page has following js in the souce:*

jQuery('.datePicker').n2datepicker({ firstDay:1, dateFormat:'dd.mm.yyyy', // etc

*in jquery 'yy' is already four digits, thats why its writing yer twice I think.
What could be wrong?
*

Incorrect path mapping in Framework/Extensions/Web/Slideshow.cs

Framework/Extensions/Web/Slideshow.cs line 183:

ImageHref = f.Substring(baseDir.Length).Replace('\\', '/'),

That turns this path:
"C:\git\n2cms\src\Mvc\Dinamico\upload\Images\copter_wide.jpg"

-> Into ->

"c/Mvc/Dinamico/upload/Images/copter_wide.jpg"

Doesn't look like its building the path correctly, considering that relativeBasePath already contains the web path you need to follow.

I think it should be using:

System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath

instead of:

System.Web.Hosting.HostingEnvironment.MapPath("/").TrimEnd('/', '\\')

Cheers (:

N2 ASPX files don't work in the designer

hi. Today i discovered a problem with .aspx ContentItem template using standard Top+SubMenuMaster. Designer View fails with message

"The master page has one or more <asp:Content> controls that do not correspond with <asp:ContentPlaceHolder> controls in the Master Page
Correct the problem in Code View"
But the code compiled without any problems. I asked mr. Google about the problem and it seems that it is in invalid title declaration
<title id="t" runat="server" title="<%$ CurrentPage: Title %>" />
<title /> instead of <title></title>. But changing the tag leads to configuration exceptions with messages about misconfigurated n2-namespaced server controls.
Can it be fixed?

Items set for future publication show as drafts and sometimes get stuck.

It appears that the future publish gets jammed up if you future publish the same item twice (on top of each other). We also found that if you have "hang over" future publish items, then they will cause the publish to "jam up".

``

First off, we love this product! It is outstanding.

Okay. So I am baffled. Here is the series of events.

1.Create a new posting (basic type nothing special)
2.Save it by select "Save and Publish in the Future"
3.Set the date to a future date.
4.Date comes and goes and the "Published Date" says it is published but the "State" is still "Draft".

We are trying to figureo ut why the state won't move to "Published" instead. So, it doesn't render for a non-logged in user since it is a "Draft" state instead of a "Published" state.

We are currently using version 2.1.1. Help would be greatly appreciated. Cheers!!!

comments

kingdango wrote Mar 19 at 11:44 AM

Me too, any updates?

Me too, any updates?

DangerMouseParker wrote Mar 22 at 8:18 AM

We did discover a way to get around this. It appears that the future publish gets jammed up if you future publish the same item twice (on top of each other). We also found that if you have "hang over" future publish items, then they will cause the publish to "jam up". So odds are, you have some future publish items "stuck" that are always causing this to fail. Take a look. Hope that help.

We did discover a way to get around this. It appears that the future publish gets jammed up if you future publish the same item twice (on top of each other). We also found that if you have "hang over" future publish items, then they will cause the publish to "jam up". So odds are, you have some future publish items "stuck" that are always causing this to fail. Take a look. Hope that help.
``

Language association & copy/paste bug

This problem manifests itself in seeing 'duplicate' pages, or rather pages which aren't a child of the parent page, in the Translations screen of the Edit UI. We've managed to figure out that this is because a page in the one language tree had a language association to another page in the same language tree. Here are steps required to reproduce this issue on a newly created N2 project (run the N2.Edit project and setup a new "Content Focus" site).

Take the English "Features" page and copy/paste it underneath the Swedish homepage
Use the Translations view to associate the UK features page to the copy just created under Sweden
Drag & drop or Cut/Paste the Swedish Features page back into the English part of the page tree. You'll need to give it a new name such as "features2"
View the translations of either Features page - you should see duplicates for a number of the pages - strangley on my copy it only shows up duplicates for the bottom 4 pages. These duplicates are actually the associated language version of that page in the same tree

I'm not sure what the best way to tackle this issue is. I think that the Cut/Paste function should remove any language associations when happening between language branches?

One way to fix this is to move the 2nd "Features" tree back into another language branch and unassociate the two before moving it back, but the "unassociate" command only unassociates the two pages themselves and not any of their children. So it's a potentially laborious process to properly fix the broken pages. I'm not sure whether this is another bug or expected behaviour?

Edit.Install.FixClass not respecting tablePrefix

Correction, "N2" is the default prefix, which can be overriden in config file, so:

The page should be looking into MYSCHEMA.SOMEPREFIXITEM table and not MYSCHEMA.SOMEPREFIXN2ITEM as said initially.

Collections.CountFilter.Filter returns the wrong items

When using the Collections.CountFilter.Filter returns the wrong items.

Let's say you have 22 items and wan't to page these. Page size is 5. For page the last page it's not the 3 last items that are return, but the last 5 items.

So Collections.CountFilter.Filter(e.Items, 20, 5) should return item 20, 21, 22, but instead return item 18, 19, 20, 21, 22.

// Johan

Incorrect type check in DefinitionBuilder.AddContainable

Hi,
there is a method N2.Definitions.Static.DefinitionBuilder.AddContainable which performs the following type check:

Type editableType = EnsureType<IEditable>(editable.Type);

before doing anything.

The thing that it may be called for the Editabled and Containers as well. Please see N2.Definitions.Static.DefinitionBuilder.UpdateDefinitionFromConfiguration method.
And in case of Containers, exception will be thrown since Container is not IEditable.

Seems to be that its better to check for IContainable rather than for IEditable: Type editableType = EnsureType<IContainable>(editable.Type);
since casting from IEditable to IContainable is possible, or perform different type check per each case.

N2CMS 2.2.1

Ensure .CurrentItem property is not null

Firstly, the prologue: In some situations, it is usefull to reuse N2's masterpage(s) (now it's a single Top+SubMenu.master, right?) without having any content items beneth OR without active N2.Engine at all (let say for the purpose of prototyping, or in process of migration to N2, or in any other situation where we're interested only in master page's ContentPlaceholder hierarchy, but not in any N2-related functionality, embedded into said master page).

Some time ago reusing Top+SubMenu.master was possible: you took an arbitrary plain old .aspx page, assigned this master -- and it just worked. Since some time it isn't possbile any longer because of YSOD, compaining about .CurrentItem being zero from different parts of Top+SubMenu.master.

As it turned out, the reasong lays in the UrlParser class, which cannot find a matching ContentItem for an url and there is no fallback mechanism in place. (Indeed, there is a NotFoundHandler available, but yet I didn't find a way to start it anyhow, but manually with a custom initializer.) I've tried fixing master itself, isolating every CurrentItem usage with a guardian if(null == .. , but it prooved quite ineffective and intrusive to N2' codebase.

Finally i've found quite simple solution, which basically is to set a CurrentItem to current StartPage if nothing else works. Hopefully, it doesn't break anything. At least, having CurrentItem == null seems to be useless anyway.

Index: UrlParser.cs
===================================================================
--- UrlParser.cs    (revision 442)
+++ UrlParser.cs    (working copy)
@@ -124,7 +124,7 @@
            if (url.Length == 0)
                return current;
            else
-               return current.GetChild(url) ?? NotFoundPage(url);
+               return current.GetChild(url) ?? NotFoundPage(url) ?? this.StartPage;
        }

         /// <summary>Returns a page when  no page is found. This method will return the start page if the url matches the default content page property.</summary>

sorry, indeed it seem to be a breaking change: in edit mode CurrentItem detection logic behaves differently, thus setting CurrentPage to StartPage disables certain fallback case, which i try now localizing.


esteewhy wrote Sep 17, 2008 at 3:39 AM

Let me clarify my last comment: what i do mean under "CurrentItem detection logic" in edit mode.

I have a user control ("ascx") which inherits from N2.Web.UI.ContentUserControl. To enable a fallback case when inherited CurrentItem == null i've borrowed the following snippet from N2.Templates.Web.UI.WebControls controls: ItemUtility.FindCurrentItem(Parent)

so i was able to hide base CurrentItem with smth like this:

get { return base.CurrentItem ?? ItemUtility.FindCurrentItem(this.Parent) 

Now if i apply my patch, the right-side of ?? op. doesn't fire, so the question arise: am i using ContentUserControl AND ItemUtility correctly ? Isn't calling FindCurrentItem sufficient to get a current item, thus avoiding CurrentItem property (consequently, stopping inheriting from ContentUserControl, hence assuming my fix was a valid one) ? Why are there so many ways to get a current item in N2 public API? (N2.Context.CurrentPage, Find.CurrentPage, ItemUtility.*, UrlParser.CurrentPage) What's a preferred way ?


libardo wrote Sep 17, 2008 at 1:58 PM

The many ways are due to legacy and a touch of sloppiness. Which ones do you think are most logical to keep?

Which ones of the ContentUserControls are you using. The special stuff in the <TPage, TItem> is related to resolving the item with expression builders. They are evaluated during compilation, before the item is added to the control tree.

I think having the CurrentPage as null is kindof useful. It makes it more clear when an url doesn't match any content. Having content from the start page appear by default isn't ideal.

What I'll definitely do is fixing the master page so that it can work anyway.


esteewhy wrote Sep 18, 2008 at 6:49 AM

Yes, simply fixing Top+SubMenu.master will do the job.


esteewhy wrote Sep 19, 2008 at 3:45 AM

..as to the most obvious way to obtain a CurrentItem. My personal favorite if, of course, ContentPage<T>.CurrentItem/ContentControl<T>.CurrentItem. What i love the most about this design is the way it mentally aligns with ASP.Net Mvc approach. This fact alone is a good reason to explain N2 to new-comers by stressing on it's architectural similarities with MVC, which now becoming a hot topic among .Net community.

Wiki Addon Improvements

  1. Remove Title="Untitled Page" from the page definitions
  2. Remove the MasterTemplateFile from the page definitions
  3. Move all pages to a Views subfolder

NuGet package update re-adds configuration changes

Because there are sections of the web.config file that are setup by NuGet but expected to be changed by the user, when you do update-package from the nuget command line, the web.config will have duplicates of the section and the section.

To bypass this, create a new NuGet pacakge, something like N2CMS.InitialSetup that contains these transformation elements, and only update that package when something in those two sections ACTUALLY needs to be changed, and make sure that's at least a minor revision. Other config transforms that are NOT expected to be changed can remain in the main N2CMS or wherever they currently are. That (current) package would have a dependency on the other (new) package, so users would have one more time they would have to deal with the hassle of manually fixing the web.config, but after that, there would be no need to edit it just for a simple N2 update.

Add button does not appear on parts with EditableChildren

n2 version 2.4.9.2

I recently noticed that when you create a part and within that part you can add EditableChildren.

So far its fine but when you add more EditableChildrens the "Add" button does not show. I have marked the
EditableChildren on the image below. As you would see the "Links" button is missing.
editableschildren

Note that this problem occurs only the first time after adding an item with editable children part that in turn has editable children as a part. It can be worked around by performing a save and preview/publish.

This is however very confusing to our users who administer the actual content in N2. I do believe this is a recent regression as we haven't ran into this problem before.

Login + ReturnURL fix

At the moment, you are always redirected to the login page by N2. However, when you want to navigate a user directly to specific page, that behavior is not wanted. Here is the fix. It is a setting so the user is always able to use the old behavior of the N2 login control.

  1. Templates/Items/LoginItem.cs
    [EditableCheckBox("Return to url if possible", 150)]
    public virtual bool ReturnToUrlIfPossible
    {
        get { return GetDetail<bool>(ReturnToUrlIfPossibleProperty, false); }
        set { SetDetail(ReturnToUrlIfPossibleProperty, value); }
    }
    private const string ReturnToUrlIfPossibleProperty = "ReturnToUrlIfPossible"; 
  1. Templates/UI/Parts/Login.ascx
    void LoginBox_LoggedIn(object sender, EventArgs e)
    {
        // Get the return url
        string defaultUrl = (CurrentItem.LoginPage != null) ? CurrentItem.LoginPage.Url : string.Empty;
        string returnUrl = defaultUrl;

        // Retrieve return url if required
        if (CurrentItem.ReturnToUrlIfPossible)
        {
            // First, retrieve the url
            returnUrl = FormsAuthentication.GetRedirectUrl(Page.User.Identity.Name, false);

            // Decode the url correctly
            int safeCounter = 10;
            while ((safeCounter > 0) && (!string.IsNullOrEmpty(returnUrl)) && (!returnUrl.StartsWith("/")))
            {
                // Decrease the counter to prevent lock ups
                safeCounter--;

                // Try to decode the url again
                returnUrl = Server.UrlDecode(returnUrl);
            }

            // In case the safe counter expired, use default url
            if (safeCounter <= 0) returnUrl = defaultUrl;
        }

        // Redirect
        Response.Redirect(returnUrl, true);
}

User dashboard upon login

Instead of start page preview, I would like to present user with my custom page that would serve as a dashboard with information about last edited pages, expired pages, pages waiting for publications, etc. I know how to implement this as a plugin, but how to make N2 open ("call") my plugin right after login

Pinger supplies a tokenized URL to WebClient

As part of the Scheduling/KeepAlive, Pinger.cs supplies a tokenized URL to a WebClient without first parsing it.
src/Mvc/MvcTemplates/N2/Resources/KeepAlive/Pinger.cs line 42.

 string response = wc.DownloadString(url);

Should be.

 string response = wc.DownloadString(Url.ParseTokenized(url));

Save and preview doesn't apply to child on the page

I would like to report a bug, when saving and previewing a page which has a child part on it, the content in the part live immediately. I think this should not happen. Thanks.


I would like to explain my issue again, the problem is, for example, a page has a EditableChildren property Links which saves some links, if I edit the links and click Save and Preview button, the links are live immediately and the end site users can see them although I just want to preview my editing.


andpoulsen wrote Jun 21, 2011 at 5:56 AM

I also struggle a bit with this, because it makes the preview function useless, since I cannot possibly make our content editors understand when preview works and when it doesn't.
Touched on the subject in the discussion forum: http://n2cms.codeplex.com/discussions/232343

I also struggle a bit with this, because it makes the preview function useless, since I cannot possibly make our content editors understand when preview works and when it doesn't.
Touched on the subject in the discussion forum: http://n2cms.codeplex.com/discussions/232343


libardo wrote Jun 21, 2011 at 7:36 AM

The trickyness is associating parts that needs to be published and change tracked in tandem. This is in the todo list and will be fixed eventually. Possible workarounds for the time being:

  • Disabling versions for this certain type of page [Versionable(No)]
  • Using a new editor area in v2.2 ("setings"), where no preview is available

The trickyness is associating parts that needs to be published and change tracked in tandem. This is in the todo list and will be fixed eventually. Possible workarounds for the time being:

  • Disabling versions for this certain type of page [Versionable(No)]
  • Using a new editor area in v2.2 ("setings"), where no preview is available

andpoulsen wrote Jul 3, 2011 at 1:16 PM

I'd like to object to rating this issue as impact: low.
The impact of this issue is that content editors are actually publishing pages,when they think they are only previewing them. That is pretty bad in my opinion.

I'd like to object to rating this issue as impact: low.
The impact of this issue is that content editors are actually publishing pages,when they think they are only previewing them. That is pretty bad in my opinion.


Naz wrote Jul 21, 2011 at 2:56 PM

I am also suffering this problem has anyone found a way to work around this issue?

I am also suffering this problem has anyone found a way to work around this issue?


andpoulsen wrote Jul 27, 2011 at 1:36 AM

I think the best you can do is to vote to have the issue fixed, in case you haven't already done so.

I think the best you can do is to vote to have the issue fixed, in case you haven't already done so.

ContentRoute not taking DefaultExtension into account

I have an ASP.NET MVC 3 site using N2. I've been trying to use the Extension attribute of the Host sections' Web element to make every page appear to have a .html extension (I need to be able to scrape the site, and it makes things a lot easier if the pages are served up with extensions by default.)

I've got this in my web.config file under the host element.

        <web extension=".html" />

When I try to browse to a url ending in .html, I get a 404 error.

I've looked through the code, and as far as I can see the following is happening: the code in RequestLifeCycleHandler calls the GetCurrentPath method of the RequestPathProvider (line 70). This then calls the RequestPathProvider.ResolveUrl method which, at line 57, removes the extension and default document, before using UrlParser.ResolvePath to resolve the Url. This works correctly and the page is resolved, however there is no need to rewrite the request (RequestLifeCycleHandler line 73) so nothing is changed at this point.

The request then goes into the standard MVC processing pipeline, and ContentRoute.GetRouteData method is called. This calls into the base GetRouteData, which calls into GetRouteDataForPath. This then calls into UrlParser.ResolvePath, but does nothing to remove default document or extension. As a result, the page cannot be correctly resolved and I get my 404.

I'm intending to change ContentRoute to strip the default extension and default document before calling UrlParser.ResolvePath, and I'm happy to send a pull request once I've done it. What I'm hoping is that someone can confirm this is the correct way to deal with it. It will end up with some duplication between ContentRoute and RequestLifecycleHandler - perhaps the handling of default extension/document is better done in UrlParser or ContentItem? Since UrlParser handles adding the default extension when BuildUrl is called, it would make sense to me to push the responsibility of stripping it out again into UrlParser as well , but this is a bigger refactoring than I'm comfortable making at the moment.

Thanks
Jon
comm

Image Gallery can't be dragged onto any webforms page

Hi, just started using this CMS & i am very impressed with it so far!

unfortunately, when i try to add an image gallery (to any zone) on a Plain Content Page i get the following error when i try to access the content page (the gallery & images work fine)

Cannot add ~/Templates/UI/Views/ImageGallery.aspx defined by N2.Templates.Items.ImageGallery's TemplateUrl property to a page. Either refrain from adding this item to a page or override TemplateUrl and have it return the url to a user control.

any suggestions on fixing this? i downloaded the source a few days back

thanks

Save and Publish Without Any Changes Creates a New Version

I was running into a situation where some HTML wasn't being displayed correctly. But before I figured that out, I thought it might have been a versioning issue, so I would save and publish what I thought was correct without making any changes. When doing this, a new version was created. A feature suggestion might be, that if you save and publish with out any changes the user is informed that no changes were made and therefor no no version will be published.ThanksDaniel

N+1 Issue when viewing pages with no CMS Content

Our site gets around 450,000 page loads per day on our search result pages which have SEO friendly urls eg. /category/location. Some of the popular category pages have CMS content and only a handfull of location pages have content. There are around 55k unique location pages, which means we have a large number of urls which have no CMS content.

I've been investigating some performance issues with N2 on our site which mainly seem to be occurring with the pages which don't have CMS content which was causing us around 14 queries to the n2 database and it seem's to be the same two queries 7 times. This is with caching enabled and after it's warmed up.

There appeared to be two issues causing this.

Firstly the CachingUrlParserDecorator does not add to the cache if there is no pathdata for the requested url. I understand we don't want to cache an empty pathdata as it will mean invalidating the cache will be tricky when CMS content is added for that URL in the future. However adding some First level caching (HttpContext.Current.Items) has reduced the number of queries from 14 to 10.

The secound issue was bieng caused by the UrlParser and the CurrentPage property which would always try to resolve the path if the CurrentPage is null which in the case of a page without any cms content means every time you access the property it does and database hit.

Having gone through the source code from what I can see for all WebRequest there should be no reason why webContext.CurrentPage is null unless that page has no content. I think the only case is if it's a ThreadContext used by Schedulers. So I've modified the CurrentPage property and check webContext.IsWeb == true and return webContext.CurrentPage and not incur the database hit.

This had further reduces the queries from 10 to only 2.

Ideally we we like to have no queries for pages with no content but from looking at the source that will require using the global cache and thinking about a cache invalidation strategy.


I've managed to remove all queries no non cms and this issue is now solved in my latest check-in.

https://github.com/nazjunaid/n2cms/commit/8a217071968205b4860f4c4000e6571ed8bd4fd0

I also noticed a race condition issue so added some locking in there.
I normalize the urls by removing parameters we don't care about so if you have content pages with multiple variations in the url it shouldn't incur extra db hits and caching.

These changes has vastly improved the performance of our site.


Naz wrote Sep 26, 2011 at 1:07 PM

I have found another issue related to this and think some more work needs to be done to get N2 to work the way we use it in a more performable manner.

Once i'm happy with my code and fully tested it I will ask for a pull in the meantime please hold off taking my changes.

I have found another issue related to this and think some more work needs to be done to get N2 to work the way we use it in a more performable manner.

Once i'm happy with my code and fully tested it I will ask for a pull in the meantime please hold off taking my changes.

Make ContentController more unit testable

Hi,

The abstract Index() method on the ContentController class is giving me grief when trying to build controllers that are easily unit-testable. For example, I need to pass a parameter to my Index method, usually I would do it as so:

public ActionResult Index(int? tab /* tab is picked up from the Request collection */)
{
// Do stuff with tab
}

With the ContentController.Index() method made abstract I have to implement it with no parameters. This leaves me with the only option of accessing Request["tab"] directly, meaning that I have to go to the trouble of Mocking Request just for this one value (as well as manually parsing the value to an int in my Controller).

I have attached a patch that removes the abstract Index method from ContentController. It also makes the CurrentItem and Engine properties publically settable so that tests can set these to mock instances etc. All tests still pass and the MVC sample application appears to run without issues. The one unfortunate side-effect is that any existing controllers that derive from ContentController will need the override keyword removing from their Index method declaration, but it's nothing a quick find & replace won't fix.

Hope this can make it into the source,
Steve

Patch file

Index: examples/Mvc/wwwroot/Controllers/NewsContainerController.cs
===================================================================
--- examples/Mvc/wwwroot/Controllers/NewsContainerController.cs (revision 515)
+++ examples/Mvc/wwwroot/Controllers/NewsContainerController.cs (working copy)
@@ -1,11 +1,7 @@
 ๏ปฟusing System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Web;
 using System.Web.Mvc;
 using MvcTest.Models;
 using N2.Web.Mvc;
-using N2.Collections;
 using MvcTest.Views.NewsContainer;

 namespace MvcTest.Controllers
@@ -13,7 +9,7 @@
    [Controls(typeof(NewsContainer))]
    public class NewsContainerController : ContentController<NewsContainer>
    {
-       public override ActionResult Index()
+       public ActionResult Index()
        {
            return View("Index", new NewsContainerViewData { Container = CurrentItem, News = CurrentItem.GetNews()});
        }
Index: examples/Mvc/wwwroot/Controllers/NewsController.cs
===================================================================
--- examples/Mvc/wwwroot/Controllers/NewsController.cs  (revision 515)
+++ examples/Mvc/wwwroot/Controllers/NewsController.cs  (working copy)
@@ -1,11 +1,7 @@
 ๏ปฟusing System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Web;
 using System.Web.Mvc;
 using MvcTest.Models;
 using N2.Web.Mvc;
-using N2.Collections;
 using MvcTest.Views.News;

 namespace MvcTest.Controllers
@@ -13,7 +9,7 @@
    [Controls(typeof(NewsPage))]
    public class NewsController : ContentController<NewsPage>
    {
-       public override ActionResult Index()
+       public ActionResult Index()
        {
            var vd = new NewsViewData 
            { 
Index: src/N2.Extensions.Tests/Mvc/Controllers/AboutUsSectionPageController.cs
===================================================================
--- src/N2.Extensions.Tests/Mvc/Controllers/AboutUsSectionPageController.cs (revision 515)
+++ src/N2.Extensions.Tests/Mvc/Controllers/AboutUsSectionPageController.cs (working copy)
@@ -10,7 +10,7 @@
    [Controls(typeof(AboutUsSectionPage))]
    public class AboutUsSectionPageController : ContentController<AboutUsSectionPage>
    {
-       public override System.Web.Mvc.ActionResult Index()
+       public System.Web.Mvc.ActionResult Index()
        {
            throw new NotImplementedException();
        }
Index: src/N2.Extensions.Tests/Mvc/Controllers/ExecutiveTeamController.cs
===================================================================
--- src/N2.Extensions.Tests/Mvc/Controllers/ExecutiveTeamController.cs  (revision 515)
+++ src/N2.Extensions.Tests/Mvc/Controllers/ExecutiveTeamController.cs  (working copy)
@@ -11,7 +11,7 @@
    [Controls(typeof(ExecutiveTeamPage))]
    public class ExecutiveTeamController : ContentController<ExecutiveTeamPage>
    {
-       public override ActionResult Index()
+       public ActionResult Index()
        {
            throw new NotImplementedException();
        }
Index: src/N2.Extensions.Tests/Mvc/Controllers/RegularControllerBase.cs
===================================================================
--- src/N2.Extensions.Tests/Mvc/Controllers/RegularControllerBase.cs    (revision 515)
+++ src/N2.Extensions.Tests/Mvc/Controllers/RegularControllerBase.cs    (working copy)
@@ -10,7 +10,7 @@
    [Controls(typeof(RegularPage))]
    public class RegularControllerBase : ContentController<RegularPage>
    {
-       public override System.Web.Mvc.ActionResult Index()
+       public System.Web.Mvc.ActionResult Index()
        {
            throw new NotImplementedException();
        }
Index: src/N2.Extensions/Web/Mvc/ContentController.cs
===================================================================
--- src/N2.Extensions/Web/Mvc/ContentController.cs  (revision 515)
+++ src/N2.Extensions/Web/Mvc/ContentController.cs  (working copy)
@@ -1,24 +1,43 @@
 ๏ปฟusing System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
 using System.Web.Mvc;
 using N2.Engine;

 namespace N2.Web.Mvc
 {
    public abstract class ContentController<T> : Controller
-       where T: ContentItem
+       where T : ContentItem
    {
-       protected virtual IEngine Engine
+       private IEngine _engine;
+       private T _currentItem;
+
+       public virtual IEngine Engine
        {
-           get { return ControllerContext.RouteData.Values["ContentEngine"] as IEngine; }
+           get
+           {
+               if(_engine == null)
+                   _engine = ControllerContext.RouteData.Values["ContentEngine"] as IEngine;
+
+               return _engine;
+           }
+           set
+           {
+               _engine = value;
+           }
        }
-       protected virtual T CurrentItem
+
+       public virtual T CurrentItem
        {
-           get { return ControllerContext.RouteData.Values["ContentItem"] as T; }
+           get
+           {
+               if(_currentItem == null)
+                   _currentItem = ControllerContext.RouteData.Values["ContentItem"] as T;
+
+               return _currentItem;
+           }
+           set
+           {
+               _currentItem = value;
+           }
        }
-
-       public abstract ActionResult Index();
    }
-}
+}
\ No newline at end of file
Index: src/N2.Extensions/Web/Mvc/FallbackContentController.cs
===================================================================
--- src/N2.Extensions/Web/Mvc/FallbackContentController.cs  (revision 515)
+++ src/N2.Extensions/Web/Mvc/FallbackContentController.cs  (working copy)
@@ -1,19 +1,16 @@
 ๏ปฟusing System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
 using System.Web.Mvc;

 namespace N2.Web.Mvc
 {
-   [Controls(typeof(ContentItem))]
+   [Controls(typeof (ContentItem))]
    public class FallbackContentController : ContentController<ContentItem>
    {
-       public override ActionResult Index()
+       public ActionResult Index()
        {
            ContentItem item = CurrentItem;
-           
+
            return View(item.TemplateUrl, item);
        }
    }
-}
+}
\ No newline at end of file

Enable feature to obligate the users to browse the server file system to choose an image

It is a good solution to obligate the users to browse the server file system to choose an image.

I have modified the class N2.Details.EditableImageAttribute adding:

 // attribute
 private bool readOnly = false;

 public bool ReadOnly
 {
get { return readOnly; }
set { readOnly = value; }
}

 protected override Control AddEditor(Control container)
 {
FileSelector selector = new FileSelector();
selector.ID = Name;
if (ReadOnly)
    selector.Attributes["readonly"] = "readonly";
container.Controls.Add(selector);
return selector;
}

It would be nice if it is added by default in the next release!!

Thanks,
Pedro

New saving options

I think that some new options when saving items will be very helpful.
I want next options to be included after "Save and publish":
"Save and create new"
"Save and return to edit this item"

Webinstaller throws 'WebForms UnobtrusiveValidationMode requires a ScriptResourceMapping...' with Dynamico 2.4.12.19 nuget package

I created a new MVC 4 project in Visual Studio 2012 (windows 8) and installed the Dinamico Templates for N2 CMS 2.4.12.19 using .NET 4.5.

When added the requestValidationMode=2.0 and a connection string. After that I started the project which started the webinstaller (N2/Installation/Default.aspx).

That throwed an exception: "WebForms UnobtrusiveValidationMode requires a ScriptResourceMapping for 'jquery'. Please add a ScriptResourceMapping named jquery(case-sensitive)."

To fix this I added: in the section.

Not sure if that is the appropriate fix. But if it is, then perhaps it should be added to web.config as a comment to make the install smoother?

Decouple FileSystem from FileManager and create an interface to allow to store files in the DB, Cloud, etc

It was proposed in the forum post:

http://n2.codeplex.com/Thread/View.aspx?ThreadId=48643

"I have created a new HttpHandler to store the assets that I upload to the CMS in a database instead of the file system. But I have found the FileManager from the N2.Edit project needs to be modified and a new table, n2File created in the database.

I believe that by integrating the handler in the N2.Core, and making the File Manager in N2.Edit use a generic HttpHandlerBase interface would be an improvement. We could then choose whether to use a database, filesystem, cloud platform etc depending on a value in the config file.

The reason we have used a database in our projects is so we don't have to replicate the files when we use a load balancer, and for permission issues on the File System."

"My proposal to integrate it into N2 CMS is:

In N2.Edit Project, the file \Edit\FileManagement\Default.aspx.cs should use an interface and not access to the file system directly. The interface should have the methods:

IFileManager{
SiteMapProvider()
UploadFile()
CreateFolder()
DeleteFile() & DeleteDirectory() ?
Delete()
DeleteValidation()
}

The method SiteMapProvider shoud return Web.FileSiteMapProvider() if the File System is being used or SqlSiteMapProvider if the assets are stored in the database."

I attach a file with the classes that we've used to store the files in the DB, it would be nice to refactor and integrate it in the core.

I'll be glad to help explain how to integrate it.

Thank you
Pedro Alonso

pedropaf wrote Mar 4, 2009 at 10:31 AM

I've been implementing the IFileSystem interface using Linq but not yet finished. I don't know if I will have enough time to finish it, so maybe I'll go back to the workaround I did the last time.

I attach the code I've done. What I think that should be done is instead creating a handler for the files stored in the database would be a better solution to implement a VirtualPathProvider, when the files are requested via GetFile() check the prefix (/Upload) then call IFileSystem.GetFile() if it's true, otherwise call base.GetFile(). Then the reference from the browser to the assets stored in the database would be a real path, and not a path to a handler.

Thank you for any feedback.

I've been implementing the IFileSystem interface using Linq but not yet finished. I don't know if I will have enough time to finish it, so maybe I'll go back to the workaround I did the last time.

I attach the code I've done. What I think that should be done is instead creating a handler for the files stored in the database would be a better solution to implement a VirtualPathProvider, when the files are requested via GetFile() check the prefix (/Upload) then call IFileSystem.GetFile() if it's true, otherwise call base.GetFile(). Then the reference from the browser to the assets stored in the database would be a real path, and not a path to a handler.

Thank you for any feedback.

mrshrinkray wrote Mar 21, 2009 at 4:14 AM

Ideally you'd want to tie this in so that some link checking could be done as well (at the moment links are stored with static urls).

Ideally you'd want to tie this in so that some link checking could be done as well (at the moment links are stored with static urls).

XML Export issue

XML Export does not always work correctly. We need to write unit tests for the XML Export functionality and fix any bugs that are found here.

Culprit page: http://www.shrinkrays.net/code-snippets/csharp/-net-xml-comment-cheat-sheet.aspx

If you scroll down you can see the page has its own XML in it (stored as < > not < and >) and the main problem is the CDATA chunk. The exception is throwing on ElementWriter:public void WriteCData(string value){ writer.WriteCData(value);}One answer might be to base64 encode all strings in case the Detail has invalid XML in it.

There are some ancient changes someone suggested merging in. They're related to import/export, so i'd like to take a chance to share 'em. Here what they do, as far as i recall:

  • respect detail's Name during import when the detail is enclosed by a DetailsCollection (otherwise, the Name is taken from enclosing collection). (Of course, this change doesn't make much sense, since by default ContentDetail.Name is always overridden by enclosing DetailCollection.. Just for the sake of completeness..)
  • apply a DateTime format fix (once mentioned here in a context of Updated/Created properties) to the DateTimeDetail
Index: Serialization/DetailCollectionXmlReader.cs
===================================================================
--- Serialization/DetailCollectionXmlReader.cs  (revision 662)
+++ Serialization/DetailCollectionXmlReader.cs  (working copy)
@@ -34,7 +34,10 @@

            if (type != typeof(ContentItem))
            {
-               collection.Add(Parse(navigator.Value, type));
+               collection.Add(ContentDetail.New(
+                   collection.EnclosingItem,
+                   attributes["name"],
+                   Parse(navigator.Value, type)));
            }
            else
            {
@@ -42,7 +45,10 @@
                ContentItem referencedItem = journal.Find(referencedItemID);
                if (referencedItem != null)
                {
-                   collection.Add(referencedItem);
+                   collection.Add(ContentDetail.New(
+                       collection.EnclosingItem,
+                       attributes["name"],
+                       referencedItem));
                }
                else
                {
@@ -50,7 +56,10 @@
                                    {
                                        if (e.AffectedItem.ID == referencedItemID)
                                        {
-                                           collection.Add(e.AffectedItem);
+                                           collection.Add(ContentDetail.New(
+                                               collection.EnclosingItem,
+                                               attributes["name"],
+                                               e.AffectedItem));
                                        }
                                    };
                }
Index: Serialization/XmlReader.cs
===================================================================
--- Serialization/XmlReader.cs  (revision 662)
+++ Serialization/XmlReader.cs  (working copy)
@@ -51,10 +51,15 @@

        public static DateTime? ToNullableDateTime(string value)
        {
-           if (string.IsNullOrEmpty(value))
-               return null;
+           DateTime _result;

-            return DateTime.Parse(value, System.Globalization.CultureInfo.InvariantCulture).ToLocalTime();
+           return DateTime.TryParse(
+                   value,
+                   System.Globalization.CultureInfo.InvariantCulture,
+                   System.Globalization.DateTimeStyles.None,
+                   out _result)
+               ? _result.ToLocalTime()
+               : default(DateTime?);
        }

    }

Automate upgrading discriminators via code

We are developing a CMS for multiple sites. Sometimes we need to handle changing type names of Content Items. With multiple sites and multiple environments, this take a long time to do manually. In production you would turn of the FixClass.aspx page so it has be be something more automatically.

The way we have handled it is to make a IPluginInitializer with AutoInitialize, that handles the upgrade which will get a connection to the database and run a couple of queries to the database.

 [AutoInitialize]
public class DiscriminatorUpgradeInitializer : IPluginInitializer
{
    public void Initialize(IEngine engine)
    {
        var handler = engine.Resolve<IDiscriminatorUpgradeHandler>();

        handler.DeleteObsolete("ReallyOldContentItem");
        handler.UpdateObsolete<NewContentItem>("OldContentItem");
    }
}

This works, although much of the code in the implementation of IDiscriminatorUpgradeHandler is copied and refactored from FixClass.aspx.cs. It would be great if this functionality could be provided from N2, because then it's much easier for us and others to automate that process.

Also, InstallationManager is also hard to mock since it doesn't have virtual properties/methods or implementing an interface. The only this from it that we needed in this case is the GetConnection and GetCommand. So I would also suggest to refactor those two methods into an interface.

If you think this is a good idea, I'm happy to provide some more code on what we have done.

Sort on Multiple Columns

PropertySortDirection and DetailSortDirection set the SortOrder on QueryBuilder, while if they would just append, they would allow for sorting on multiple columns.

cookieless authentication does not work in /N2

I'm behind a proxy right now and I can't log into my N2 site. When I enter my username and password the page just reloads because the session is getting lost for some reason.

If I add a login widget to my N2 site, I notice that a cookieless session URL is generated and I am logged in. However, if I go to /N2 (keeping the session ID in the URL), the left pane goes to the login screen and the buttons on the top page cause me to leave my session ID behind.

Change theme and preview

with the Template Project:
If you change the Theme of site, and you trying to use the "Preview" function, instead of "Save and Publish", the preview doesn't show the new theme selected.

Possible for N2 admin to crash in some case: Dinamico Login - object reference not set

I pulled the latest source from GitHub and built everything. The Dynamico site comes up, but when clicking on Loging I get null reference exception in ViewContentHelper, HasValue method. This code blows up if Current.Item[detailName] == null

 public bool HasValue(string detailName)
    {
        return Current.Item[detailName] != null && !("".Equals(Current.Item[detailName]));
    }

it could be (this works):

 return Current.Item != null && Current.Item[detailName] != null && !("".Equals(Current.Item[detailName]));

 [NullReferenceException: Object reference not set to an instance of an object.]
 N2.Web.Mvc.ViewContentHelper.HasValue(String detailName) +66
 System.Func`2.Invoke(T arg) +0
 N2.Web.Mvc.HasValueHelper.TryGetMember(GetMemberBinder binder, Object& result) +75
 CallSite.Target(Closure , CallSite , Object ) +130
 ASP._Page_Dinamico_Themes_Default_Views_Shared_LayoutPartials_Head_cshtml.Execute() +1145
 System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +207
 System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +81
 System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +88
 System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance) +220
 System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer) +115
 System.Web.Mvc.HtmlHelper.RenderPartialInternal(String partialViewName, ViewDataDictionary viewData, Object model, TextWriter writer, ViewEngineCollection viewEngineCollection) +279
 System.Web.Mvc.Html.RenderPartialExtensions.RenderPartial(HtmlHelper htmlHelper, String partialViewName) +71
 ASP._Page_Dinamico_Themes_Default_Views_Shared__Layout_cshtml.Execute() +76
 System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +207

MVC Posted Form Data is null

Created a form (part).
Name, EMail, Other with corresponding fields for data.
No data is submitted in the mail.
Only the Fieldnames
??

In N2.Templates.Mvc.Models.Parts.Questions.TextQuestion

add the lines marked with >>>> below. Otherwise all input type=text and textareas will miss their name-attributes

public override MvcHtmlString CreateHtmlElement()
    {
        if (Rows == 1)
        {
            string html = new TagBuilder("input")
                .Attr("type", "text")
                .Attr("size", (Columns ?? 60).ToString())
            >>>>               .Attr("name", this.ElementID)
                .ToString(TagRenderMode.SelfClosing);
            return MvcHtmlString.Create(html);
        }
        else
        {
            string html = new TagBuilder("textarea")
                .Attr("rows", Rows.ToString())
                .Attr("cols", (Columns ?? 60).ToString())
               >>>>            .Attr("name", this.ElementID)
                .ToString();
            return MvcHtmlString.Create(html);
        }

    }

Two EditableChildren on the same page

I used N2CMS 1.6 earlier, and before a month ago a made decision to switch to version 2.1.1. Then I noticed a new bug that was not present in 1.6:

If you on the same put 2 or more EditableChildren, clicking "Add Item" goes good, but clicking "Add Item" for second time, causes page to completely crash with following error :

"An error has occurred because a control with id 'ctl00$ctl00$Frame$Content$ie$ctl31' could not be located or a different control is assigned to the same ID after postback. If the ID is not assigned, explicitly set the ID property of controls that raise postback events to avoid this error."

This ID is related to second "Add Item" button, and I'm pretty sure that problem is deep in N2CMS core, as this didn't happened in previous versions.

Does UpdateLinks handle SearchResultsPage?

When such property is created:

 [EditableLink]
 public virtual ContentItem SearchResultsPage { get; set; }

Editor should pick an item from the tree, but not URL should be stored, but ID of the page. In such case moving a page in the tree won't break links.

[Code quality] N2.Utility.CurrentTime isn't always used

Hi guys,

There is a N2.Utility.CurrentTime() function. But it isn't used on all N2 codes. Like:

\src\Framework\N2\Security\SecurityManager.cs

    public virtual bool IsPublished(ContentItem item)
    {
        return (item.Published.HasValue && DateTime.Now >= item.Published)
            && (!item.Expires.HasValue || DateTime.Now < item.Expires.Value);
    }

\src\Framework\N2\ContentItem.cs

    string INode.ClassNames
    {
        get
        {
            StringBuilder className = new StringBuilder();

            if (!Published.HasValue || Published > DateTime.Now)
                className.Append("unpublished ");
            else if (Published > DateTime.Now.AddDays(-1))
                className.Append("day ");
            else if (Published > DateTime.Now.AddDays(-7))
                className.Append("week ");
            else if (Published > DateTime.Now.AddMonths(-1))
                className.Append("month ");

            if (Expires.HasValue && Expires <= DateTime.Now)
                className.Append("expired ");

            if (!Visible)
                className.Append("invisible ");

            if (AuthorizedRoles != null && AuthorizedRoles.Count > 0)
                className.Append("locked ");

            return className.ToString();
        }
    }

I think the DateTime.Now isn't used. This should be N2.Utility.CurrentTime().

Please review and fix this.

Thanks

EditableFileUpload does not support Required parameter

A custom model type that inherits from N2.ContentItem and uses other attributes like EditableText can create a property such as

[EditableFileUpload(Title="File to attach")]
public virtual string DocumentFile { get; set; }

but if you try to make this a required property

[EditableFileUpload(Title="File to attach",Required=true)]
public virtual string DocumentFile { get; set; }

The page will throw an exception when you try to create this item, saying that the ControlToValidate cannot be found:

Control 'DocumentFile' referenced by the ControlToValidate property of 'DocumentFile_rfv' cannot be validated.

The expected behavior is that the validator is correctly wired to the input and the ContentItem cannot be saved without uploading a file.

Memory leak in ImageResizer.Resize and .GetResizedImage

The resized bitmap references are not explicitly disposed within a using(){} clause. As the Bitmap class only uses a few bytes of managed memory, it is considered lowest-priority by the garbage collector. Under load, this manifests itself as a problem quickly: http://blogs.msdn.com/b/tess/archive/2009/02/03/net-memory-leak-to-dispose-or-not-to-dispose-that-s-the-1-gb-question.aspx

Some more light reading: http://www.nathanaeljones.com/blog/2009/20-image-resizing-pitfalls

As the author of ImageResizer (http://imageresizing.net), I'd be interested in working with you on an integration; LGPL licensing of the essential edition is certainly an option.

I'm working with others to standardize a common URL API for images at http://riapi.org/ - If you decide to stay with the current handler approach, perhaps you'll collaborate with us?

Best regards,
Nathanael Jones

Edit User Role not working

Hi,

I have the latest version of N2 2.4 and when i save a a Users role, its not not showing there but its saved.

I noticed when i kill the application , rerun the application and edit the same user, the value is checked, meaning it was saved.

Users

faester wrote Nov 13, 2012 at 3:58 AM

The problem also exists in 2.7.7. It is apparently releated to (caching?) and the N2.Security.ContentRoleProvider since the issue does not occur when we substitute that with a standard SqlRoleProvider. (We use many custom roles.)

The problem also exists in 2.7.7. It is apparently releated to (caching?) and the N2.Security.ContentRoleProvider since the issue does not occur when we substitute that with a standard SqlRoleProvider. (We use many custom roles.)

Items of open generic types cause an exception during NHibernate configuration initialization

If in loaded assemblies there is at least one item with unbound type argument, then a whole application fails to load with the message: "Invalid type owner for DynamicMethod."

A quick illustration:

public class MyBaseItem<T>: ContentItem {} 
    //Open generic type, is not supposed to be used as a 
    // real content item, but is still considered by N2 
    // configuration builder as a valid definition

public class MyItem: MyBaseItem<int> {} 
    //Closed generic type is meant to be used

The simplest fix is to just ignore open generics (along with abstract types) in DefinitionBuilder.FindConcreteTypes().

(Considerably harder solution might be providing a mechanism for programmers to indicate their intention to ignore a class by means of an attribute, but does the opposite really make sense?)

If there's no objection, i could commit the fix.

P.S.: a bit of theory for curious minds: http://hyperthink.net/blog/reflecting-over-generic-types/

//singleton with multiple item collections
public class BlogContainer : ContentItem {
    public PostContainer Posts { get { return (PostContainer)this.GetChild("Posts"); } }
    public PageContainer Pages { get { return (PageContainer)this.GetChild("Pages"); } }
    public CategoryContainer Categories { get { return (CategoryContainer)this.GetChild("Categories"); } }
}

//base children collection -- should be igonored by NH
public class BaseContainer<ItemType>: ContentItem
{
    public IEnumerable<ItemType> Items {
        get { return this.GetChildren().OfType<ItemType>(); }
    }

    public IEnumerable<ItemType> ItemHierarchy {
        get { return Find.EnumerateTree(this).OfType<ItemType>(); }
    }
}

//concrete collections
public class PageContainer: BaseContainer<Page> {}
public class PostContainer: BaseContainer<Post> {}
public class CategoryContainer: BaseContainer<Category> {}

Proposed Patch:

Index: DefinitionBuilder.cs
===================================================================
--- DefinitionBuilder.cs    (revision 515)
+++ DefinitionBuilder.cs    (working copy)
@@ -112,7 +112,7 @@
        {
            foreach(Type t in typeFinder.Find(typeof (ContentItem)))
            {
-               if(t != null && !t.IsAbstract)
+               if(t != null && !t.IsAbstract && !t.ContainsGenericParameters)
                {
                     yield return t;
                }

20081216-n2-blogengine

Use GET instead of POST on the search-form

I tested the template with all the goodies and I have a small comment on the search site addon.Personally I'd prefer if I could easily go back to search result, but if you use the back-button you would have to post the search form over again.Wouldn't it be easy and better to just let the form submit the query using the querystring instead of post-data? Like very other search engine ;-)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.