tags:

views:

805

answers:

4

How do I create a partial view that has a form with assigned id? I got as far as:

using (Html.BeginForm(?action?,"Candidate",FormMethod.Post,new {id="blah"}))

Partial view is used for both Create and Edit so first parameter ?action? will be different. I can't figure out what value of ?action? supposed to be

+4  A: 

Pass in the action to be performed via ViewData.

In your action that renders the view, create a ViewData item for the postback action. In your form reference this ViewData item to fill in the action parameter. Alternatively, you can create a view-only model that includes the action and the actual model as properties and reference it from there.

Example using ViewData:

using (Html.BeginForm( (string)ViewData["PostBackAction"], "Candidate", ...

Rendering actions:

public ActionResult Create()
{
     ViewData["PostBackAction"] = "New";
     ...
}


public ActionResult Edit( int id )
{
     ViewData["PostBackAction'] = "Update";
     ...
}

Example using Model

public class UpdateModel
{
     public string Action {get; set;}
     public Candidate CandidateModel { get; set; }
}

using (Html.BeginForm( Model.Action, "Candidate", ...

Rendering actions:

public ActionResult Create()
{
     var model = new UpdateModel { Action = "New" };

     ...

     return View(model);
}


public ActionResult Edit( int id )
{
     var model = new UpdateModel { Action = "Update" };

     model.CandidateModel = ...find corresponding model from id...

     return View(model);
}

EDIT: Based on your comment, if you feel that this should be done in the view (though I disagree), you could try some logic based off the ViewContext.RouteData

<%
    var action = "Create";
    if (this.ViewContext.RouteData.Values["action"] == "Edit")
    {
        action = "Update";
    }
    using (Html.BeginForm( action, "Candidate", ... 
    {
 %>
tvanfosson
This will work but I don't really want to change Controller code to handle something that View should be able to figure out
Dmitriy Shvadskiy
I added alternative this is entirely view-based, though I would think that the proper place to control what action to postback to would be in the controller.
tvanfosson
Yep. That's exactly what I was looking for. The action name is inViewContext.RouteData.Values["action"]
Dmitriy Shvadskiy
@Dmitriy -- updated to use values property in example. I still think that the controller ought to control the flow in the app either by choosing a view with a fixed postback url or supplying the postback url to a view with a dynamic one. Views should responsible for rendering, not control logic.
tvanfosson
Thank you for the info as it solved an issue I had with extending some conditional functionality to a Partial. Re the code example of using the ViewContext.RouteData I needed to cast it as a string for the comparision as below but was great for getting me in the right direciton. <%if ((string)this.ViewContext.RouteData.Values["action"] == "Create") {%> - Thanks, Norman
Norman
A: 

<% html.RenderPartial("MyUserControl", Model.ID) %>

Al Katawazi
A: 

I guess I was not clear enough with the question. What I ended up doing is splitting Request.RawUrl to get controller name and action name

 string[] actionUrlParts = ViewContext.HttpContext.Request.RawUrl.Split('/');
 using (Html.BeginForm(actionUrlParts.Length >= 2? actionUrlParts[2] : "",
        actionUrlParts.Length >= 1 ? actionUrlParts[1] : "", FormMethod.Post, new { id = "blah" }))

Kind of ugly but it works. Is there a better way to get an action name inside the partial view?

Dmitriy Shvadskiy
A: 

Pass nulls as action and controller. Extension will use just current action and current controller

using (Html.BeginForm(null, null, FormMethod.Post, new { id="Model" }))

Action generated for form will be the same as parent view of this partial view.

It generates

<form action="/Orders/Edit/1" id="Model" method="post">

for url http://localhost:1214/Orders/Edit/1

... and this

<form action="/Orders/Create" id="Model" method="post">

for url http://localhost:1214/Orders/Create

rodpl