Elaine K
Elaine K

Reputation: 517

Cshtml to RTF page break disappears when file opens in Word

thanks in advance for any help you can offer. I have been digging through the various posts here on SO trying to solve a missing page break issue. I have a number of cshtml templates that are rendered using a Razor template engine to produce an RTF file. When the file is opened in Word it completely dumps the html that contains the "break" style used to make a page break. The rest of the template renders exactly as designed. I am thinking that maybe my problem is I'm not rendering out the file correctly in the first place.

Sample .cshtml file starts with:

<div style="width: 100%;" class="newpage">
    <p align="center" style="text-align:center">NOTICE</p> 
        <table>
             ....middle html content....
        </table>
    <p class="newpage"></p>
</div>

I've tried putting the page break at the beginning and the end just to see if it made any difference and it didn't.

The razor call that gets the .cshtml file is like this:

 newNotice.Body = RazorEngine.Razor.Parse(Notifications.GetTemplate(NotificationTemplate.MyTemplate2), data, NotificationTemplate.MyTemplate2.ToString());
 return newNotice;

Then I render out the RTF file in the following code where the style for the page break exists:

protected void ProduceNotification(Notification notice, string title)
{
    Response.Clear();
    Response.Buffer = true;
    Response.AddHeader("content-disposition", "attachment;filename=" + title);
    Response.ContentType = "application/rtf";
    EnableViewState = false;
    var stringWrite = new StringWriter();
    var sb = new StringBuilder();
    sb.Append(@"<html>
                  <head>
                    <title></title>
                    <style type='text/css'>
                        .body {
                            margin: 5em;
                            background-color: white;
                            width: 100%;
                            height: 100%;
                            font-family: Calibri;
                        }
                        .spacing {
                            line-height: 1.5em;
                        }
                        .newpage {
                            mso-special-character:line-break;
                            page-break-before:always;
                            clear: both;
                        }
                    </style>
                  </head><body>");
    sb.Append(notice.Body);
    sb.Append("</body></html>");
    stringWrite.WriteLine(sb);
    ClearChildControlState();
    Response.Write(stringWrite.ToString());
    Response.End();
}

When I open up the file in Word, the page breaks are not being respected so I saved the file to .html to see what the mark up looks like and here's what I see:

In the style definition section it shows the style:

p.newpage, li.newpage, div.newpage
{mso-style-name:break;
mso-style-unhide:no;
mso-margin-top-alt:auto;
margin-right:0in;
mso-margin-bottom-alt:auto;
margin-left:0in;
page-break-before:always;
mso-pagination:widow-orphan;
font-size:12.0pt;
font-family:"Times New Roman","serif";
mso-fareast-font-family:"Times New Roman";
mso-fareast-theme-font:minor-fareast;}

But in the document where the html should show the element with the class on it, it looks like this instead (this is in the middle of the html output):

<div>
    <p align=center style='text-align:center'>NOTICE </p>
        <table>
            ......middle html content.....
        </table>
</div>

Notice that the style and class are missing from the div tag and the p tag is missing all together. What I can't figure out is, is the conversion to RTF deleting these for some reason or is it the Razor Templating Engine that's stripping out the text? I've also tried changing this to output an .doc format also but the result has been the same.

Upvotes: 0

Views: 788

Answers (1)

Elaine K
Elaine K

Reputation: 517

So the aggravating answer also turned out to be the simplest one. The style was applying to p, li, or div elements but only if the element has some kind of content:

 <div class='newpage'>&nbsp;</div>

As long as I used one of the correct elements, it works as long as there is some kind of content (in this case just a space). Once I had it working, I also had to address the issue of it adding an extra blank page to the output since originally I had the line in the cshtml file itself. Instead I moved it to the code behind.

I created a var to hold the last list item, as demonstrated in this SO post here.

var lastItem = myList.Last();

foreach(var d in myList)
{
    newNotice.Body += RazorEngine.Razor.Parse(Notifications.GetTemplate(NotificationTemplate.MyTemplate2), data, NotificationTemplate.MyTemplate2.ToString());
    if(!ReferenceEquals(d, lastItem))
        newNotice.Body += "<div class='newpage'>&nbsp;</div>";
}

Upvotes: 0

Related Questions