Tal Bronfer
Tal Bronfer

Reputation: 759

TextBox not displayed when rendering form with Html.BeginForm

I've just begun learning ASP MVC 4, and I'm working on a basic exercise, which is a book hosting website.

I'm currently working on a controller for adding a new book to the repository. The view for the appropriate action is strongly-typed to the Book class as its model. Book is a very simple model consisting of title, author and so forth.

My AddBook controller currently looks like this: (I haven't implemented any database insertion logic on POST, yet)

public class AddBookController : Controller
{
    [HttpGet]
    public ActionResult AddBook()
    {
        return View();
    }

    [HttpPost]
    public ActionResult AddBook(Book book)
    {
        return View();
    }

}

My view is also very simple:


@model Bookshare.Models.Book

@{
    ViewBag.Title = "AddBook";
}

Add a new book

@using (Html.BeginForm()) { Html.TextBoxFor(model => model.Title); Html.TextBoxFor(model => model.Author); Html.TextBoxFor(model => model.PublishingCompany); Html.TextBoxFor(model => model.ReleaseYear); Html.TextBoxFor(model => model.Summary); }

And yet, when I call this action, all I can see is the "Add a new book" header and the submit button for the form. No text boxes whatsoever. This also happens if I use the plain old Html.TextBox syntax. Viewing the page's source reveals just an empty form tag.

What am I doing wrong here?

Upvotes: 3

Views: 2501

Answers (2)

ataravati
ataravati

Reputation: 9145

The way you are using the Html Helper is wrong. The TextBoxFor method is not a void method that you call like Html.TextBoxFor(...);. It returns an MvcHtmlString object that you want to write on the page. Therefore, you use it like below:

@Html.TextBoxFor(model => model.Title)   

@ in the above code is the equivalent of Response.Write in classic asp.

So, your Form in its simplest way should be like this:

@using (Html.BeginForm())
{
    @Html.TextBoxFor(model => model.Title)
    @Html.TextBoxFor(model => model.Author)
    @Html.TextBoxFor(model => model.PublishingCompany)
    @Html.TextBoxFor(model => model.ReleaseYear)
    @Html.TextBoxFor(model => model.Summary)
}

But, that will render all TextBoxes next to each other without a Label, and without a placeholder for validation message. Replace each TextBox in your View with something like below to format them on the page properly and to add a Label and a Validation Message placeholder.

<div class="editor-label">
    @Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
    @Html.EditorFor(model => model.Title)
    @Html.ValidationMessageFor(model => model.Title)
</div>

EditorFor will be rendered as TextBox for string properties.

Upvotes: 4

gyurisc
gyurisc

Reputation: 11492

It turns out that for the correct form you need only the following. The controller for the create method can be like this:

    public ActionResult Create()
    {
        return View();
    }

My working view looks like this, your fields of course will be slightly different:

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

    <fieldset>
        <legend>Book</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.Author)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Author)
            @Html.ValidationMessageFor(model => model.Author)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Title)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Title)
            @Html.ValidationMessageFor(model => model.Title)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Description)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Description)
            @Html.ValidationMessageFor(model => model.Description)
        </div>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

With this I can see the form rendered in the browser.

Upvotes: 2

Related Questions