views:

335

answers:

3

EDIT

I put my solution on a share site. Like that you'll be able to see what I'm talking about. You can download it here : http://www.easy-share.com/1909069597/TestRenderAction.zip

To test it, start the project (let the create form empty) and click the Create button. You'll see what happen.

It's only a example project. I don't care to persist my object to the database for now. I care to make my example work.

I got the following controller :

public class ProductController : Controller
{
    public ActionResult List()
    {
        IList<Product> products = new List<Product>();

        products.Add(new Product() { Id = 1, Name = "A", Price = 22.3 });
        products.Add(new Product() { Id = 2, Name = "B", Price = 11.4 });
        products.Add(new Product() { Id = 3, Name = "C", Price = 26.5 });
        products.Add(new Product() { Id = 4, Name = "D", Price = 45.0 });
        products.Add(new Product() { Id = 5, Name = "E", Price = 87.79 });

        return View(products);
    }

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

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Create(Product product)
    {
        return View(product);
    }
}

The following model :

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public double Price { get; set; }
}

My Product/List.aspx :

<h2>List</h2>

<table>
    <tr>
        <th></th>
        <th>
            Id
        </th>
        <th>
            Name
        </th>
        <th>
            Price
        </th>
    </tr>

<% foreach (var item in Model) { %>

    <tr>
        <td>
            <%= Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) %> |
            <%= Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ })%>
        </td>
        <td>
            <%= Html.Encode(item.Id) %>
        </td>
        <td>
            <%= Html.Encode(item.Name) %>
        </td>
        <td>
            <%= Html.Encode(String.Format("{0:F}", item.Price)) %>
        </td>
    </tr>

<% } %>

</table>

<p>
   <% Html.RenderAction("Create"); %>
</p>

My Product/Create.ascx :

<%= Html.ValidationSummary("Create was unsuccessful. Please correct the errors and try again.") %>

<% using (Html.BeginForm("Create", "Product", FormMethod.Post)) {%>

    <fieldset>
        <legend>Fields</legend>
        <p>
            <label for="Id">Id:</label>
            <%= Html.TextBox("Id") %>
            <%= Html.ValidationMessage("Id", "*") %>
        </p>
        <p>
            <label for="Name">Name:</label>
            <%= Html.TextBox("Name") %>
            <%= Html.ValidationMessage("Name", "*") %>
        </p>
        <p>
            <label for="Price">Price:</label>
            <%= Html.TextBox("Price") %>
            <%= Html.ValidationMessage("Price", "*") %>
        </p>
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>

<% } %>

<div>
    <%=Html.ActionLink("Back to List", "Index") %>
</div>

The problem is that when I hit the create button and I got an error (like empty field), the return view only return my Create.ascx control. It's doesn't return the Product/List.asxp page with in my Create.ascx control with the errors. That's what I would like it's does.

Any idea how I can solve that problem ?

I use Asp.Net Mvc 1 with Asp.Net Futures (which have the Html.RenderAction).

A: 

Are the names of your text fields the same as the properties in your Product object?

Does your product object declare it's properties like this;

public string Name {get;set;}

You must have getters and setters on your objects.

EDIT

Wait, are you wanting fields from your list View to be available in the post to your create action? If yes then you need to place the BeginForm at the View level and not the PartialView level.

Only fields contained within the begin form will be posted to your controller.

EDIT 2

Ah, I think I see it now.

In your controller I think you should do a product.IsValid to check first.

But in your html you should also do this;

<%= Html.TextBox("Id", Model.Id) %>

You need to fill in the value for the text box.

Hope this is what you were after.

griegs
Yes, I declare them like that
Melursus
I put more code. May be not you will better understand my problematic. What I want it's a listing and a create widget (that's why I use RenderAction) in the same page. The first time I load the page, that's work correctly. The problem come when I try to add a new product. The post action work correctlt but the returned view is the create.ascx view without the listing and without the style.
Melursus
A: 
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Product product)
{
  ...
  return View("List");
}

or

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Product product)
{
  ...
   return RedirectToAction("List", "Product");
}
mxmissile
The second option work but my Create form isn't validate. I mean I didn't see the error validation message.
Melursus
A: 

Hey,

your controller should work like this:

public class ProductController : Controller
{
  IList<Product> products;

  public ProductController( )
  {
    products = new List<Product>();
    products.Add(new Product() { Id = 1, Name = "A", Price = 22.3 });
    products.Add(new Product() { Id = 2, Name = "B", Price = 11.4 });
    products.Add(new Product() { Id = 3, Name = "C", Price = 26.5 });
    products.Add(new Product() { Id = 4, Name = "D", Price = 45.0 });
    products.Add(new Product() { Id = 5, Name = "E", Price = 87.79 });
  }

  public ActionResult List( )
  { 
    return View(products);
  }

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

  [AcceptVerbs(HttpVerbs.Post)]
  public ActionResult Create(Product product)
  {
    products.Add(product);
    return View("List", products);      
  }
} 

Additionally, you need to call RenderPartial instead of RenderAction, because otherwise your POST method will be invoked (due to you did a post-command by submitting the form):

<p> 
   <% Html.RenderPartial("Create"); %> 
</p> 

This should work, you only need to persist your products list, as it will reset with every postback.

I hope this helped you :)

Steffen