2

I am passing a list of strings into a razor view page and I'd like to check if there are any errors before rendering the HTML asking to correct them.

My code compiles fine but generates a compile error when the page is rendered. The error is:

Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.

Compiler Error Message: CS1501: No overload for method 'Write' takes 0 arguments

And here is the code that I'm trying to render:

@model UNICH.Settings.SettingsModel
@{
    ViewBag.Title = "Edit";
}
@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)


    @{ 
         // Retrieve the server generated config errors from the ViewData
         List<string> errors = ViewData["ConfigErrors"] as List<string>;

         if( errors != null && errors.Count > 0 )
         {
             // We have some errors to display 
            <div>
                <h3>The following errors need attention before the configuration can be saved</h3>
                <ul>
                    @foreach( var error in errors)
                    {
                        // Display the errors that require attention
                        <li>
                            @error
                        </li>
                    }
                </ul>
            </div>
        }
     }    

    <fieldset>
        <legend>Database Configuration</legend>
        <table>
            <tr>
                <th>
                    Parameter
                </th>
                <th>
                    Value
                </th>
                <th>
                    Error
                </th>
            </tr>
            <tr>
                <td>
                    <h4>
                        Database Type</h4>
                </td>
                <td>
                    @Html.DropDownListFor(model => model.DBType, ViewData["DBTypes"] as SelectList, "select a value")
                </td>
                <td>
                    @Html.ValidationMessageFor(model => model.DBType)
                </td>
            </tr>
            <tr>
                <td>
                    <h4>
                        Server Name</h4>
                </td>
                <td>
                    @if( Model.DBType != "Oracle")
                {
                        @Html.EditorFor(model => model.DBServerName)
                }
                </td>
                <td>
                    @Html.ValidationMessageFor(model => model.DBServerName)
                </td>
            </tr>
            <tr>
                <td>
                    <h4>
                        Instance Name</h4>
                </td>
                <td>
                    @Html.EditorFor(model => model.DBInstanceName)
                </td>
                <td>
                    @Html.ValidationMessageFor(model => model.DBInstanceName)
                </td>
            </tr>
            <tr>
                <td>
                    <h4>
                        DB User Name</h4>
                </td>
                <td>
                    @Html.EditorFor(model => model.DBUsername)
                </td>
                <td>
                    @Html.ValidationMessageFor(model => model.DBUsername)
                </td>
            </tr>
            <tr>
                <td>
                    <h4>
                        Database Password</h4>
                </td>
                <td>
                    @Html.EditorFor(model => model.DBPassword)
                </td>
                <td>
                    @Html.ValidationMessageFor(model => model.DBPassword)
                </td>
            </tr>
        </table>
    </fieldset>
    <div>
        <p>
            <input type="submit" value="Save" />
        </p>
    </div>
}
<div>
    @Html.ActionLink("Discard Changes", "Index")
</div>
8
  • 2
    Just wondering, why are you calling ToString() on a string? Commented Nov 18, 2011 at 14:29
  • 1
    @RichardD, It's just an act of frustration and trying anything to get it to work. :o( Commented Nov 18, 2011 at 14:34
  • 1
    Fair enough :D I've had many a similar thing. Commented Nov 18, 2011 at 14:35
  • Still worked fine for me. Is that all of your code? Does it tell you what line the error occurs on? Commented Nov 18, 2011 at 14:49
  • 1
    @TeamWild That makes sense, you can keep it inside the BeginForm block but just remove the @{ } surrounding it. You should post your solution as the answer and accept it. Commented Nov 18, 2011 at 15:28

2 Answers 2

3

You don't need the @{ and } around the server side code which casts the ViewData value into a List<string>. And as a side note you wouldn't need to cast if you had used view models instead of the ViewData weakly typed structure. And of course if you had used strong typing you wouldn't need to wrap it in @{ ... } and you wouldn't get any error. Conclusion: never use ViewBag/ViewData in an ASP.NET MVC application. Always use view models and strongly typed views.

Here's the correct code (correct in italic since it works but not recommended as per my previous side note):

@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)

    // Retrieve the server generated config errors from the ViewData
    List<string> errors = ViewData["ConfigErrors"] as List<string>;

    if( errors != null && errors.Count > 0 )
    {
        // We have some errors to display 
        <div>
            <h3>The following errors need attention before the configuration can be saved</h3>
            <ul>
                @foreach( var error in errors)
                {
                    // Display the errors that require attention
                    <li>
                        @error
                    </li>
                }
            </ul>
        </div>        
    }

    <fieldset>
        ...
    </fieldset>

    <div>
        <p>
            <input type="submit" value="Save" />
        </p>
    </div>
}

<div>
    @Html.ActionLink("Discard Changes", "Index")
</div>
Sign up to request clarification or add additional context in comments.

3 Comments

Now I'm confused... Your answer is the same as RichardD's suggestion BUT your comment about not using ViewBag/ViewData goes against all the tutorials I've been working through. That doesn't mean your wrong... I'll give it a go.
@TeamWild, the problem with tutorials is that they tend to oversimplify things and unfortunately teach people bad practices such as ViewBag/ViewData which introduce weak typing into your views and transform them into spaghetti code where you will be fighting against this weak typing in a strongly typed language such as C#. That's what view models are designed to do: reflect your view's requirements. So if in you view you need to show a list of errors than this list of errors should be a property of your view model and you should be using SettingsViewModel instead of SettingsModel.
Thank your for the explanation. It makes a lot of sense. I moved the sting list into my model and it's made for much cleaner looking code in the controller, view and even the service that populates the model.
0

The problem relates to the location of the code block. Moving the code block outside of the Html.BeginForm() brackets resolved the issue.

    @{ 
    // Retrieve the server generated config errors from the ViewData
    List<string> errors = ViewData["ConfigErrors"] as List<string>;

    if( errors != null && errors.Count > 0 )
    {
        // We have some errors to display 
        <div>
            <h3>The following errors need attention before the configuration can be saved</h3>
            <ul>
                @foreach( var error in errors)
                {
                    // Display the errors that require attention
                    <li>
                        @error
                    </li>
                }
            </ul>
        </div>
    }
}
@using (Html.BeginForm())
{
     ...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.