Alternate path in Orchard - c#

I've created my own class which adds alternates to the relevant collection:
ShapeMetadata.Alternates.Add("DansForm");
This works fine, but only when DansForm is in the Views root.
I want to keep all the DansForm alternates in a directory.
How can I reference a path?
What I've tried:
ShapeMetadata.Alternates.Add("Forms/DansForm");
ShapeMetadata.Alternates.Add("/Forms.DansForm");
ShapeMetadata.Alternates.Add("Forms.DansForm");
ShapeMetadata.Alternates.Add("Forms\\DansForm");
ShapeMetadata.Alternates.Add("Forms__DansForm");
ShapeMetadata.Alternates.Add("Forms_DansForm");
Doesn't find any of them.

You cant organise shape templates into directories. Orchard has a hardcoded list of directories it searches for shape templates:
public IEnumerable<string> SubPaths() {
return new[] { "Views", "Views/Items", "Views/Parts", "Views/Fields" };
}
I guess this is for performance reasons. I suppose you could write an additional implementation of IShapeTemplateHarvester to find shapes in your own folders, but seems like overkill just to make it a little more organised. I think you'll just have to suffer the mess of views. Sorry!

Related

A better alias list?

We have a system that manages generic physical resources. There are over 500 individual resources. The system is used for many different things and to make the software easier to write we use aliases.
For example, a physical resource TG67I9 is given an alias of "RightDoor". When code is written RightDoor is used instead of TG67I9 making the code more readable. This alias list is loaded as a text file with references to resources and their aliases. This system uses literally hundreds of different alias lists to reference the same physical resources.
This type of setup has two major shortcomings. First, when resources are called using their aliases, they are passed in as strings. Door.Open("RightDoor") for example. This does not give any tooltips or smart anything making the code more difficult to write. It basically requires constantly referencing the alias list. Is it RightDoor or Right_Door or right-door or... you get the idea. The second is that there is no validation of parameters until execution. All the compiler knows is that a string is passed in and then it's happy. Only when the code is run, the function tries to access the resource through its alias and fails because it can't find right-door because it's supposed to be RightDoor. An error is displayed. This requires tedious debugging and running the code over and over to weed out any bad aliases.
Is there a better way to do this? Such that an alias list can be made with a cross-reference of physical resources to their alias names and after the list is made that tooltips could appear suggesting resources. (Assume that a new system could be written from scratch)
I'm using the latest .NET with VisualStudio 2017 and C# to write the code.
The simplest approach is most likely a "string enum":
public class Resources {
public const string
LeftDoor = "TG67I8",
RightDoor = "TG67I9";
}
Sample use:
Door.Open(Resources.RightDoor);
Hovering over .RightDoor in VS shows a tooltip (constant) string Resources.RightDoor = "TG67I9"
Right-clicking .RightDoor and selecting Find All References will show where the variable is used.
Another option can be adding the strings in the Resources section of the Project Properties, and then:
using YourProjectNameSpace.Properties;
...
Door.Open(Resources.RightDoor);
That is a bit slower, because the resource(s) are retrieved at run-time, but allows to load the resources from a custom external file separate from the executable.
Use a static class with constants. I have done the same many times and still do. Plus .NET does this as well.
public static class PhysicalResources
{
public const string One = "Uno";
public const string Two = "Deux";
// ...
}

How to switch between resx files (not using culture)

What I am trying to do:
I am working on a chat bot service where I have different channels of access. On one channel I want to use my Customer.resx file and on another channel I want to use my Worker.resx file.
The problem:
I know how localization works to switch between Worker.en-US.resx and Worker.es-MX.resx, but I am unsure how to switch from one normal resx file to a completely different context one. These will each be translated into other languages so I can't simply use Customer.en-US.resx and Worker.es-MX.resx as a workaround. I do know that I can build a custom culture using the CultureAndRegionInfoBuilder, but I would rather do this in a simpler way than that, something along the lines of how you do localization. I am currently building custom cultures using this method and I have Resources.worker-en-US.resx and similar for customer, but this is a round-about way and I know there must be a better way.
For clarification I know I can grab a resource file with ResXResourceSet, but the idea was that I would like to have two separate resource files with localization for each (worker.en-US and customer.en-US).
I would combine both of these as into one because resx's are really tied to cultures/languages. You can use a strategy pattern to get the right strings at the right time.
interface IStrings { string Foo { get; } }
class WorkerStrings : IStrings { ... }
class CustomerStrings : IStrings { ... }

How to make all static files like css/images/js files not be processed by asp.net mvc?

Is it possible that static files not be processed by the asp.net mvc engine?
Can I do this at the IIS level or something? (without ofcourse creating a seperate IIS website for static files)
You need to create an ignore route for the specific types of files you don't want to be served through ASP.NET MVC.
Add the following to your routes, for the types of files you want to ignore.
The following works for files in the root:
routes.IgnoreRoute("{file}.css");
routes.IgnoreRoute("{file}.jpg");
routes.IgnoreRoute("{file}.gif");
If you want to ignore files in a specific directory, you can do this:
routes.IgnoreRoute("assets/{*pathInfo}");
If you want to combine these into one route, you can (e.g., ignore specific types of files in a directory):
routes.IgnoreRoute("{assets}", new { assets = #".*\.(css|js|gif|jpg)(/.)?" });
This overload of IgnoreRoute accepts a url (the first argument) and a Constraints object of things to ignore.
Since the RouteConstraints in ASP.NET MVC can be implemented multiple ways (including a regex), you can put standard regexes in the second argument.
If you want to implement a custom constraint, there is lots of useful documentation on that subject (say, if your constraint is dynamic at runtime).
Be careful, #george-stocker's answer works for static files in the root directory only!!!
To catch static files in all possible directories/subdirectories, use an ignore rule with a "condition", like this:
routes.IgnoreRoute("{*allfiles}", new { allfiles = #".*\.(css|js|gif|jpg|png)" });
Static files are not processed by ASP.NET MVC, unless you have a route that matches the URL of a static file. Maybe you are asking about static files processed by ASP.NET, in that case you should not use runAllManagedModulesForAllRequests="true". Here's a post with more info.
In Global.asax.cs in the beginning of method RegisterRoutes write the following:
routes.IgnoreRoute("Content/{*pathInfo}");
replacing Content with the name of a folder containing your static files.
George, however, provided More comprehensive solution

C# Factory Pattern

I am building a search application that has indexed several different data sources. When a query is performed against the search engine index, each search result specifies which data source it came from. I have built a factory pattern that I used to display a different template for each type of search result, but I've realized that this pattern will become more difficult to manage as more and more data sources are indexed by the search engine (i.e new code template has to be created for each new data source).
I created the following structure for my factory based off of an article by Granville Barnett over at DotNetSlackers.com
factory pattern http://img11.imageshack.us/img11/8382/factoryi.jpg
In order to make this search application easier to maintain, my thought was to create a set of database tables that can be used to define individual template types that my factory pattern could reference in order to determine which template to construct. I figured that I'd need to have a look up table that would be used to specify the type of template to build based off of the search result data source. I'd then need to have a table(s) to specify which fields to display for that template type. I'd also need a table (or additional columns within the template table) that would be use to define how to render that field (i.e. Hyperlink, Label, CssClass, etc).
Does anyone have any examples of a pattern like this? Please let me know.
Thanks,
-Robert
I would offer that this proposed solution is no less maintainable than simply associating a data source to the code template, as you currently have now. In fact, I would even go so far as to say you're going to lose flexibility by pushing the template schema and rendering information to a database, which will make your application harder to maintain.
For example, let's suppose you have these data sources with attributes (if I'm understanding this correctly):
Document { Author, DateModified }
Picture { Size, Caption, Image }
Song { Artist, Length, AlbumCover }
You then may have one of each of these data sources in your search results. Each element is rendered differently (Picture may be rendered with a preview image anchored to the left, or Song could display the album cover, etc.)
Let's just look at the rendering under your proposed design. You're going to query the database for the renderings and then adjust some HTML you are emitting, say because you want a green background for Documents and a blue one for Pictures. For the sake of argument, let's say you realize that you really need three background colors for Songs, two for Pictures, and one for Documents. Now, you're looking at a database schema change, which is promoted and pushed out, in addition to changing the parameterized template you're applying the rendering values to.
Let's say further you decide that the Document result needs a drop-down control, the Picture needs a few buttons, and Songs need a sound player control. Now, each template per data source changes drastically, so you're right back where you started, except now you have a database layer thrown in.
This is how the design breaks, because you've now lost the flexibility to define different templates per data source. The other thing you lose is having your templates versioned in source control.
I would look at how you can re-use common elements/controls in your emitted views, but keep the mapping in the factory between the template and the data source, and keep the templates as separate files per data source. Look at maintaining the rendering via CSS or similar configuration settings. For making it easier to maintain, considering exporting the mappings out as a simple XML file. To deploy a new data source, you simply add a mapping, create the appropriate template and CSS file, and drop them in to expected locations.
Response to comments below:
I meant a simple switch statement should suffice:
switch (resultType)
{
case (ResultType.Song):
factory = new SongResultFactory();
template = factory.BuildResult();
break;
// ...
Where you have the logic to output a given template. If you want something more compact than a long switch statement, you can create the mappings in a dictionary, like this:
IDictionary<ResultType, ResultFactory> TemplateMap;
mapping = new Dictionary<ResultType, ResultFactory>();
mapping.Add(ResultType.Song, new SongResultFactory());
// ... for all mappings.
Then, instead of a switch statement, you can do this one-liner:
template = TemplateMap[resultType].CreateTemplate();
My main argument was that at some point you still have to maintain the mappings - either in the database, a big switch statement, or this IDictionary instance that needs to be initialized.
You can take it further and store the mappings in a simple XML file that's read in:
<TemplateMap>
<Mapping ResultType="Song" ResultFactoryType="SongResultFactory" />
<!-- ... -->
</TemplateMap>
And use reflection et. al. to populate the IDictionary. You're still maintaining the mappings, but now in an XML file, which might be easier to deploy.

Hierarchy vs Merged List

Basically in my app I want to store all the nodes created by the user in a global list, say like:
GlobalComposition = { collection }
which will store nodes like:
ImageInput01, ImageInput02, Blur01, Sharpen01, Contrast01, Contrast02
What I can't decide is whether I should store them in a linear "1 dimensional" collection, or only store the base node that contains other nodes? So for something like:
ImageInput01 -> Blur01 -> Sharpen01 -> Contrast01
storing only ImageInput01.
This gives me the ability to use the same names for the action nodes that comes after the base node.
Which one would be better for unique naming system for nodes, performance, easily traversing the nodes in the composition, etc?
To me keeping the hierarchy seems more sensible but want to know people's thoughts.
Certainly a hierarchy will give you more power from a taxonomy point of view. Also, searching a tree is more efficient than searching a 1-dimensional collection in most cases.
You'd also be able to use .ToList() for a 1-dimensional collection as long as you're using .NET generic collections, as well.
Unfortunately, a hierarchy is a bit harder to implement, but generally if there is an indication of a need for it, you'll be able to take good advantage of the features it'll provide you way down the line.

Categories

Resources