I've got files with a custom extension .mcsx that are really CSharp files. I want to get code completion on these files in Visual Studio 2012, but these files are treated as plain text when I open them in VS.
I've tried to create a custom MEF extension which allows me to treat the files as having a content-type based on csharp, but I don't get autocompletion or code formatting for these documents. I might need to invoke the custom CSharp classifier for my custom content type, but I'm not sure. Can anyone help?
The custom ContentType is below:
static class ContentType
{
public const string Name = "CSScript";
[Export]
[Name(Name)]
[DisplayName("CSharp Script")]
[BaseDefinition("CSharp")]
public static ContentTypeDefinition CSharpContentType = null;
[Export]
[ContentType(Name)]
[FileExtension(".mcsx")]
public static FileExtensionToContentTypeDefinition CSharpFileExtension = null;
}
Thanks to 'Ego' on the VS forums:
You can add the custom extension file via the way below:
http://blogs.msdn.com/b/zainnab/archive/2010/08/22/using-custom-file-extension-associations-vstipenv0038.aspx
For more information about Registering a Language Service please view:
http://msdn.microsoft.com/en-us/library/vstudio/bb166421(v=vs.110).aspx
So inside of VS things are actually a bit different than the editor APIs imply -- we don't actually use content types (for the most part) to determine when to activate. Noah Richards has a great blog post that shows how to create an extension that marks another extension under an existing editor.
Related
Take the index page for example:
<h1>Hello, world!</h1>
Welcome to your new app.
<SurveyPrompt Title="How is Blazor working for you?" />
It is my understanding that this will be translated into some code using the RenderTreeBuilder which may look something like this:
builder.OpenElement(0, "h1")
builder.AddContent(1, "Hello, world!")
.
.
.
Is there a place where I can inspect the RenderTreeBuilder version of the razor pages?
I would like to start trying out RenderTreeBuilder and would like to know how it is done, for references purposes.
Apologies in advanced if this is a duplicate. I will delete this question if so.
Thanks!
You are right. The BlazorMarkup is translated into C# files that are using the RenderTreeBuilder. It is comparable to what WPF does when it comes to XAML and C# files.
After you have built your project, go to the obj/debug/net5.0/Razor/.
Keep in mind to use a debug build. Otherwise, you won't see the files.
You will see the same directory structure as in your project. Directories are listed as long as they contain razor files. Open the file, e.g., Index.razor.g.cs (.g stands for generated), and you can see the calls to RenderTreeBuilder
[Microsoft.AspNetCore.Components.RouteAttribute("/")]
public partial class Index : Microsoft.AspNetCore.Components.ComponentBase
{
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
{
__builder.AddMarkupContent(0, "<h1>Hello, world!</h1>\r\n\r\nWelcome to your new app.\r\n\r\n");
__builder.OpenComponent<BlazorApp1.Shared.SurveyPrompt>(1);
__builder.AddAttribute(2, "Title", "How is Blazor working for you?");
__builder.CloseComponent();
}
#pragma warning restore 1998
}
We have a requirement where the url of a page needs to be localizable/translated. Our existing mechanism relies on the actual published url to retrieve the page via oData. To clarify with a simplified example: we have some logic in the front end that takes the request url (which doesn't have a file extension, appends a .html extension, e.g.:
/my-awesome-path/my-awesome-page
now becomes
/my-awesome-path/my-awesome-page.html
the logic then pulls the page from oData using the query
/odata.svc/Pages?$filter=url eq '/my-awesome-path/my-awesome-page.html'
There is much more logic that we have around this to parse this SEO-friendly url and get MVC controller function parameters and other whatnots, but that's not relevant here.
Our requirement is that we cannot localize the page to give it a translated url since this would mean the entire page can't be managed in the parent web publication.
To get the localized path leading up to the page filename we simply localize the SGs. The difficulty is with the page filename. On the page's metadata we have a linked "localizable metadata" component with a field for providing a localized page filename.
What we'd like to do is update the page's URL property during the publishing/deployment process to update the page's published url with the localized page filename from this linked metadata component (assume that we have access to the localized filename field's value at any stage between start of publishing to commitment of deployment).
I've tried doing this via a custom resolver, however, at this level it appears that the page.PublishedUrl property is already established by the CM and cannot be overridden. So updating the page.FileName property doesn't do anything useful.
I've also tried directly updating the URL column in the PAGE table in Broker DB to a different name and it appears that everything continues to work, including dynamic linking and unpublishing of the page. Obviously writing a storage extension or a deployer extension to directly update the DB via jdbc is unacceptable.
Here are the options I'm thinking of:
1) try a deployer extension and use the Tridion API to update the url property
2) try writing a custom renderer that executes the url replace logic without actually updating the url in the broker. I don't favour this since request-time processing is required each time.
My question is: what is the most appropriate way to update the page url property? Will writing a custom deployer using Tridion APIs to update the URL property lead me to a dead end just like the Resolver did?
Following the points in Nuno's comment above I decided against using a custom deployer and have solved the problem using 2 event subscriptions of the Event System. On page publish I first localize the page, grab the localized filename from the localized linked metadata component and save the page. Then in a subsequent event I simply unlocalize the page. Here is my working code:
[TcmExtension("Publish or Unpublish Events")]
public class PublishOrUnpublishEvents : TcmExtension
{
public PublishOrUnpublishEvents()
{
EventSystem.Subscribe<Page, PublishEventArgs>(SetLocalizedPageFileName, EventPhases.Initiated);
EventSystem.Subscribe<Page, SetPublishStateEventArgs>(UnlocalizePageOncePublished, EventPhases.Initiated);
}
public void SetLocalizedPageFileName(Page page, PublishEventArgs args, EventPhases phase)
{
string localFilename = GetLocalilizedFileNameFromPageMetadata(page);
if (!string.IsNullOrEmpty(localFilename))
{
page.Localize();
if (page.TryCheckOut())
{
page.FileName = localFilename;
page.Save(true);
}
}
}
public void UnlocalizePageOncePublished(Page page, SetPublishStateEventArgs args, EventPhases phase)
{
string localFilename = GetLocalilizedFileNameFromPageMetadata(page);
if (!string.IsNullOrEmpty(localFilename))
page.UnLocalize();
}
private string GetLocalilizedFileNameFromPageMetadata(Page page)
{
string localFilename = string.Empty;
if (page.Metadata != null)
{
ItemFields fields = new ItemFields(page.Metadata, page.MetadataSchema);
if (fields.Contains("LocalizableMeta"))
{
ComponentLinkField localMetaField = fields["LocalizableMeta"] as ComponentLinkField;
Component component = localMetaField.Value;
ItemFields compFields = new ItemFields(component.Content, component.Schema);
if (compFields.Contains("LocalizedPageFilename"))
{
SingleLineTextField fileNameTextField = compFields["LocalizedPageFilename"] as SingleLineTextField;
localFilename = fileNameTextField.Value;
}
}
}
return localFilename;
}
}
Perhaps another option:
Store the localised URL has an additional metadata field for the page, keeping the same physical URL for the published pages.
I see your requirement is to avoid localisation of child pages, I like the way it's possible in wordpress to enter globally how URLs work, for example:
/mysite/%postname%/
It would be cool to build something similar to this within SDL Tridion, where the content title could be extracted and used at the content URL.
Either way, if you'd have to write a system that takes the 'Friendly URL' and does a look up for the actual URL, which I think would be pretty simple.
First, the overall description:
There are two Component Templates, NewsArticle and NewsList. NewsArticle is a Dreamweaver Template, and is used to display the content of a news article. NewsList is an xml file that contains aggregated information about all of the news articles.
Currently, a content author must publish the news article, and then re-publish the newslist to regenerate the xml.
Problem:
I have been tasked with having the publish of a news article also regenerate and publish the newslist. Through C#, I am able to retrieve the content of the newslist component, generate the updated xml from the news article, and merge it into the xml from the newslist. I am running into trouble getting the newslist to publish.
I have limited access to documentation, but from what I do have, I believe using the static PublishEngine.Publish method will allow me to do what I need. I believe the first parameter (items) is just a list that contains my updated newslist, and the second parameter is a new PublishInstruction with the RenderInstruction.RenderMode set to Publish. I am a little lost on what the publicationTargets should be.
Am I on the right track? If so, any help with the Publish method call is appreciated, and if not, any suggestions?
Like Quirijn suggested, a broker query is the cleanest approach.
In a situation if a broker isn't available (i.e. static publishing model only) I usually generate the newslist XML from a TBB that adds the XML as a binary, rather than kicking off publishing of another component or page. You can do this by calling this method in your C# TBB:
engine.PublishingContext.RenderedItem.AddBinary(
Stream yourXmlContentConvertedToMemoryStream,
string filename,
StructureGroup location,
string variantId,
string mimeType)
Make the variantId unique per the newslist XML file that you create, so that different components can overwrite/update the same file.
Better yet, do this in a Page Template rather than Component Template so that the news list is generated once per page, rather than per component (if you have multiple articles per page).
You are on the right tracks here with the engine.Publish() method:
PublishEngine.Publish(
new IdentifiableObject[] { linkedComponent },
engine.PublishingContext.PublishInstruction,
new List() { engine.PublishingContext.PublicationTarget });
You can just reuse the PublishInstruction and Target from the current context of your template. This sample shows a Component, but it should work in a page too.
One thing to keep in mind is that this is not possible in SDL Tridion 2011 SP1, as the publish action is not allowed out of the box due to security restrictions. I have an article about this here http://www.tridiondeveloper.com/the-story-of-sdl-tridion-2011-custom-resolver-and-the-allowwriteoperationsintemplates-attribute
I use excel through vb.net/asp.net to generate reports from a web page and then send the file down to the user. We've had some issues with Excel being super slow/inefficient/not closing (even when we keep track of the process id and try to kill it in code...). So I'm looking for some flexible alternatives. We need a replacement that can:
Allow for inidivdual cell formatting including borders (different settings on each side), background colors, font styles/coloring, etc...
Allow for cell merging
Allow for formatting (bolding in this case) of a portion of the text inside of a cell while leaving the rest of the text unchanged
Image insertion/repositioning inside a cell (not crucial)
Multiple Worksheets per Workbook
These are all the features I can think of off hand, any help or suggestiong at alternative libraries to look at would be appreciated. We are running Excel 2007 on the server but we are rolling out Office 2010 to clients so I think that might open the doors for some more supported file formats, if that helps.
After looking through the various options and performing more independent research I ended up using EPPlus, which you can get # http://epplus.codeplex.com.
Thanks for all the suggestions.
I recommend you to use the DevExpress.XtraReports from DevExpress. It is a Licensed product, but offers you a friendly toolkit for generating great and complexity reports. It is well documented and easy to use, once you define a template (REPX) you can populate it with data by assigning to each element a value as well as using [mail merge] feature which will be automatically replaced once you bind with data the report. In the core of such technology is a well OO design of classes. Once you generate the report you can export it to the most common formats: XLS, HTML, PDF, RTF...
public void GenerateReportFile(string rptFileName, string param1, int param2)
{
XtraReport report = null;
try
{
report = new XtraReport();
//-- loads the layout template (repx file)
report.LoadLayout("SomeDirectory\report_template.repx");
//-- assign data to report controls
report.FindControl("Label1", true).Text = string.Format("{0:dd/MM/yyyy}", fecha1);
report.FindControl("Label2", true).Text = string.Format("{0:dd/MM/yyyy}", fecha1);
//-- gets data from some Data Acces Layer method and assig it to the report DataSource property
DALReport dal = new DALReport();
report.DataSource = dal.GetReport1Data(ExpEmp, param1, param2);
report.DataMember = "data";
report.ExportToPdf(rptFileName, options);
}
catch { throw; }
finally { if (report != null) { report.Dispose(); } report = null; }
}
For more information refers to: http://demos.devexpress.com/XtraReportsDemos/
There is another free library for .Net iTextSharp, this library
was originally written for Java, then was translated to C# for .Net
usage. The library is mainly for PDF documents creation but some
versions also supports XLS documents creation.
GNU plot is a little bit of a pain to get to run on windows but it is a an awesome tool
It sounds like you are using a library that opens Excel and uses MS Office Excel objects to create the Excel file. Since you are using 2007 and above, you may want to consider creating the Excel file manually using a library that creates the XML (therefore, Excel doesn't open at all).
Check out ExcelLibrary.
While doing a search on this, I found this page (on StackOverflow) that provides some sample code.
Office Web Components (though dated) is free and has worked for me in the past.
If you want to spend the loot, Aspose Cells is a good way to go also.
How do I create an rss feed in ASP.Net? Is there anything built in to support it? If not, what third-party tools are available?
I'm thinking webforms, not MVC, though I suppose since this isn't a traditional page the difference may be minimal.
The .NET Framework 3.5 has added a SyndicationFeed Class which allows you to create and/or consume feeds in Atom 1.0 and RSS 2.0 formats.
SyndicationFeeds Class on MSDN
For built-in, there's nothing stopping you from using XmlDocument or XDocument (3.5) to build up the required XML for RSS. It's more work than it's worth though.
I use the Argotic Syndication Framework and serve the feeds through Generic Handlers (.ashx) with the content type set to text/xml.
The RSSToolkit is also nice. It comes with an RSSDataSource control if you're into that sort of thing. It also includes a control that will automatically insert the meta tag required for feed autodiscovery in browsers. I found the build provider for creating feeds to be a little kludgey however.
Here's an RSS framework created by a Microsoft developer: ASP.NET RSS Toolkit
Use one of the libraries available for generating the actual RSS. For example: http://www.rssdotnet.com/
If you check the code examples page at the bottom:
http://www.rssdotnet.com/documents/code_examples.html
you will find the code for clearing the content type in an ASP.net Page and outputting the RSS.
Something along the lines of (not tested, not compiled, just typed):
public void PageLoad()
{
// create channel
RssChannel _soChannel = new RssChannel();
// create item
RssItem _soItem = new RssItem();
_soItem.Title = "Answer";
_soItem.Description = "Example";
_soItem.PubDate = DateTime.Now.ToUniversalTime();
// add to channel
_soChannel.Items.Add(_soItem.);
// set channel props
_soChannel.Title = "Stack Overflow";
_soChannel.Description = "Great site.. jada jada jada";
_soChannel.LastBuildDate = DateTime.Now.ToUniversalTime();
// change type and send to output
RssFeed _f = new RssFeed();
_f.Channels.Add(channel);
Response.ContentType = "text/xml";
_f.Write(Response.OutputStream);
Response.End();
}
Hope that helps.
You could take a look at Argotic. It is a really cool framework.
http://www.codeplex.com/Argotic
Create an HTTP Handler to create a RSS feed