Alexey Kulikov
Alexey Kulikov

Reputation: 1147

razor throws an exception while rendering

I have a razor statement:

@{
    var renderColumn = new Action<OlapReportColumn>(col =>
    {
        if (col.IsSpaned)
        {
            @<th colspan="@col.Columns.Count">@col.Caption</th>;
        }
    });
}

Here is a code for render html table's header. So while I trying to call view I get an exception (translated from russian) as:

an operator can be used only assignment expression, call, increment, decrement and expectations

Here is a razor generated code part with an error:

    var renderColumn = new Action<OlapReportColumn>(col =>
    {
        if (col.IsSpaned)
        {


            #line default
            #line hidden
item => new System.Web.WebPages.HelperResult(__razor_template_writer => { // ERROR HERE!

BeginContext(__razor_template_writer, "~/Areas/Report/Views/ReportsOlap/ReportTableGenerator.cshtml", 324, 3, true);

Here a part of razor code called renderColumn

    <table id="reportGrid">
        <thead>    
            <tr>
                @foreach (var h in report.Header)
                {
                    renderColumn(h);
                }
            </tr>

What I am doing wrong in here?

Upvotes: 0

Views: 608

Answers (2)

petelids
petelids

Reputation: 12815

The Action that you've defined is behaving just like any other method in C#. The line @<th colspan="@col.Columns.Count">@col.Caption</th>; is not simply output to the output stream; instead the compiler is seeing a statement that it doesn't understand resulting in the error:

CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement

In order to write the <th colspan="@col.Columns.Count">@col.Caption</th> to the output stream you can use the WriteLiteral method:

var renderColumn = new Action<OlapReportColumn>(col =>
{
    WriteLiteral("<th colspan=" + col.Columns.Count + ">" + col.Caption + "</th>");
});

Perhaps more idiomatic than that though would be to use a Func that returns what you'd like to ouptut and then output that at the call site:

var renderColumn = new Func<OlapReportColumn, object>(col =>
{
    return Html.Raw("<th colspan=" + col.Columns.Count + ">" + col.Caption + "</th>");
});

The call would then need to be changed very slightly to tell razor that you wish to output the results:

@foreach (var h in report.Header)
{
    @(renderColumn(h))
}

Going further, there is built-in support for Funcs of this nature as described in this blog by Phil Haack. Using this method your call stays the same as the call just above but the Func becomes:

Func<OlapReportColumn, object> renderColumn2 
    = @<th colspan="@item.Columns.Count">@item.Caption</th>;

From Phil Haack's blog

Note that the delegate that’s generated is a Func<T, HelperResult>. Also, the @item parameter is a special magic parameter.

Upvotes: 1

Dhrumil
Dhrumil

Reputation: 3204

Try changing your HTML table header code from this :

@<th colspan="@col.Columns.Count">@col.Caption</th>;

to this :

@:<th colspan="@col.Columns.Count">@col.Caption</th>;

Insert that colon : immediately after @ delimeter and check if this works.

Upvotes: 0

Related Questions