Orchard query content items in my custom controller - orchardcms

The title pretty much sums it up. I created my own module in Orchard. I can access its actions via http requests like an ordinary controller in any MVC application.
I generated the controller using the command line interface and it came with IOrchardServices property that is populated in the constructor.
On my Orchard site I have a blog which I filled up with about 40 blog posts.
How can I query these blog posts from within my controller?

First I would like to start by saying: "read the source luke". You may find Orchard lacking in documentation and examples, but because it is open source, pretty much everything you want to know can be found there.
You should use the BlogPostService, inject that into your controller to get the blog posts you want.
https://orchard.codeplex.com/SourceControl/latest#src/Orchard.Web/Modules/Orchard.Blogs/Services/BlogPostService.cs
You can see it being used in several controllers within Orchard.Blogs:
https://orchard.codeplex.com/SourceControl/latest#src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogPostController.cs
https://orchard.codeplex.com/SourceControl/latest#src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogAdminController.cs
Check out the code in the BlogPostService to see how it works, it is a little confusing because blogs are content items with blog posts underneath them. If you want to learn about simpler querying of content items I would check out how the BlogService works, it is a little easier to get to grips with:
https://orchard.codeplex.com/SourceControl/latest#src/Orchard.Web/Modules/Orchard.Blogs/Services/BlogService.cs

Here is an example of what I was looking for:
var query = Services.ContentManager.Query();
var list = query.ForType(new []{"BlogPost"}).List();
var result = new List<dynamic>();
foreach (var contentItem in list) {
result.Add(new
{
title = contentItem.As<TitlePart>().Title, // dynamically typed: ((dynamic)contentItem).TitlePart.Title
text = contentItem.As<BodyPart>().Text
});
}

Related

How can set in page title with the document name in Kentico?

I need set the page title dynamically because in my node actually exist 1000 documents, so I think that exist a way to do it automatly.
I'm using Kentico 10
Use a macro. In the parent page of all your documents, you can use a field from the specific page type or use the document name.
For example if you have a page tree like this:
-Products
--Product 1
--Product 2
In the -Product pages metadata add
Page title: {%DocumentName%}
or
Page title: {%PageTypeField%}
Using the macro will allow you to dynamically get those values vs. having to code each one manually.
I'm not sure that I understand your question, but if you want:
To set page title for your documents, to be shown in browser, you should follow link in documentation.
To iterate over all nodes and update document name/ page title with some custom text, you should look into Kentico API docs. You should look into section for Updating published pages (see code example bellow):
TreeProvider tree = new TreeProvider(MembershipContext.AuthenticatedUser);
var pages = tree.SelectNodes()
.Path("/Articles/", PathTypeEnum.Children)
.WhereLike("DocumentName", "Coffee%")
.OnSite("DancingGoat")
.Culture("en-us");
foreach (TreeNode page in pages)
{
page.DocumentName = "Updated article name";
page.SetValue("ArticleTitle", "Updated article title");
page.Update();
}

What's currently the best way to pass data from a given content item to a variable Form in Orchard

I have a product package with several options in my Orchard site and I need users to be able to send an enquire based on a single option:
I've seen out there many articles about Tokens, Dynamic Forms (the examples using Dynamic Forms seem to be just for a single form type), I can think of many ways to achieve this but I don't know what is really the cleanest and fastest way to implement this functionality.
I would need a hint on what to keep researching to speed this up.
Thank you in advance
In your view, I'd wrap the button around an <a> tag something like this:
<a href="#(String.Format("/{0}/{1}", "x", y))" target="_blank">
//put button code or whatever here
</a>
Where 'x' is the extended url and y could be the query string such as: www.google.com/game/q=2
When you do this and get the redirect correct, in your driver for the page, you can get the page number from the url using something like this:
private readonly IHttpContextAccessor _httpContextAccessor;
var httpContext = _httpContextAccessor.Current();
var query = httpContext.Request.QueryString["q"];

Coded UI: Find Element(s) by CSS Selector

I am trying to build out a harness for a page so that we can write tests against it. What I would like to be able to do is use a CSS selector to find the given element or elements instead of manually modifying the SearchProperties or FilterProperties.For a web test the CSS Selector seems far more intuitive then the SearchProperties do. Is there some mechanism for doing this that I am simply not seeing?
Try this...
https://github.com/rpearsondev/CodedUI.jQueryExtensions/
It adds extension methods to the BrowserWindow object...
var example1 = browser.JQuerySelect<HtmlHyperlink>('a.class1');
var example2 = browser.JQuerySelect<HtmlListItem>('li.class2');
However, I will let you know I'm having issues with it complaining about casting errors regularly.
Try browserWindow.executeJavascript if you return a control you found via css/xpath it returns the relevant uiControl object
const string javascript = "document.querySelector('{0}');";
var bw = BrowserWindow.Launch(new Uri("http://rawstack.azurewebsites.net"));
string selector = "[ng-model='filterOptions.filterText']";
var control = bw.ExecuteScript(string.Format(javascript,selector));
HtmlEdit filter= control as HtmlEdit;
filter.Text = "Alien";
As sjdirect noted, the jQuery extensions are probably the way to go if you want to use those type of selectors.
However, it seems that you may be interested in some abstraction that doesn't require directly setting search / filter properties on the UITestControl objects.
There are good abstractions that do not use the same selectors as jQuery, but provide a readable, consistent approach for finding elements in the page and interacting with them.
I would recommend also looking into Code First and CodedUI Fluent (I wrote the fluent extensions) or even CodedUI Enhanced (CUITe).
These provide query support for that looks like (from CUITe):
// Launch the web browser and navigate to the homepage
BrowserWindowUnderTest browserWindow = BrowserWindowUnderTest.Launch("https://website.com");
// Enter the first name
browserWindow.Find<HtmlEdit>(By.Id("FirstName")).Text = "John";
// Enter the last name
browserWindow.Find<HtmlPassword>(By.Id("LastName")).Text ="Doe";
// Click the Save button
browserWindow.Find<HtmlInputButton>(By.Id("Save")).Click();

Issue in scraping with cheerio

I have been trying to scrape 10 websites for a website we are building with links to the original sites, on node.js using cheerio, problem we are getting is that some of the sites have changed which now uses ajax calls to bring their data, my question is how can we get that information, for instance trigger a button click first and then get the DOM.
secondly: same dom structure is not getting me all data, it is retrieving information for one page, but not getting the the elements on another page with identical DOM structure. any help would be appreciated.
Thanks and regards.
Edit 1: Relevant code
$('#ProductContent').filter(function(){
var price = undefined;
var ukulele = false;
var model = $(this).find('.ProductSubtitle').text().replace(/\n\s*/g,"");
if(model.indexOf(/m/i) != 0){
var description = $(this).find('.RomanceCopy').text().replace(/\n\s*|\r/g,"");
.
.code removed for brevity and the variables present here are populated
.
//this children is populated only for one page.
children = $(this).find('.SpecsColumn .SpecsTable table tbody').children('tr');
console.log('children: '+children.length)
console.log(guitar_url);
children.each(function(){
var key = $(this).children('td').first().text();
var value = $(this).children('td').last().text();
specs[key] = value;
console.log(specs);
});
Edit 2: Cherios Initialization
request(guitar_url,function(error,response,html){
if(!error){
var $ = cheerio.load(html);
$("#content #right-content").filter(function(){..children and other variables are populated inside here....})
}
})
To summarise all the comments you received:
Cheerio is minimalistic DOM reader inspired by jQuery. Its design is focused about reading data, and is not a browser emulator, where you could click a button.
Alternative is to use headless browsers like PhantomJS or CasperJS.
Those two are outside of Node.js scope, and you may have hard times transmitting the data back and forth from Node.js to headless browser.
If it is important for you to keep inside of Node.js environment, then you can use JSDOM.
All of them are more complicated to use than Cheerio, but if you want to manipulate the DOM, execute JavaScript on the DOM, etc... Then this is your best bet.
Removing the 'tbody' tags solved the problem, once they were removed it started to fetch the data normally for all three sites.

Building a list of downloadable items in Orchard 1.6

I'm fairly new to Orchard and I'm wondering about the "best" way of building a basic list of documents with a download link?
Say the scenario is this, I want to make a list of newsletters, the news letter are in PDF format and the users should be able to download then straight from the list view.
An admin, should easily be able to add a new newsletter and it should turn up in the list.
My current train of thought is to, all through the dashboard,
create a content type "Newsletter" with a title field and a Media picker field, using the media picker field to upload the PDF file.
Then create a query, with the filter on Content type "Newsletter"
Create a projection pointing to the query
However, this only gives me a list of content items, showing their title as links back to the actual content item.
I've tried adding a layout to the query and set it to display properties instead of content. By doing that I can get a list where I can control the "output" a bit more. And I've gotten it to list the title and by doing a Rewrite and putting in the MediaPicker.Url, it also displays the URL in the list. This is all good but here I get stuck..
As the MediaPicker.URL outputs the url in the format like ~/media/default/xyz/filename.pdf, I cant just put it into a a href, it doesn't give a correct download link to the file.
Soo, question is, am I thinking and doing this totally the wrong way or am I missing something obvious? All ideas and suggestions and more then welcome.
Use or adapt the following template override in your theme:
#{
var url = Model.ContentField.Url;
}
#if(Model.ContentField.Url != null) {
if (url.StartsWith("~/")) {
url = Href(url);
}
<div class="media-picker-field attachment-pdf">
<span>download</span>
</div>
}
Modify the text as needed. This template was a Fields.MediaPicker-PDF.cshtml that was used for a media picker field named PDF.

Resources