I have a asp.net mvc page which renders a record from a database, it uses RenderPartial to call another view which renders an editable list of items related to that record.
My problem is I want a since save / submit button which not only saves changes made for that record but also changes made in the RenderPartial part... I have created a method accepting POST in the RenderPartials controller but it doesn't get called? Any ideas? Or am I using RenderPartial wrongly? I did it this way so that I have a controller that handles the subset of data
Update:
I don't think I've been clear enough:
Imagine a situation where you have a page that is filled with information from lots of different tables in a database... for example imagine you have a record of a person, and then you have all the links they have to Organisations that you want to list on the page, so the page contains:
Individual Name, Email, etc...
AND
Organisation Link 1
Organisation Link 2, etc... from a link table
Because of the amount of data I want to render of the page, I figured using different controllers to render each part would make sense.. but then when saving the data do I have to use just one controller method or can I call one controller to another... I only have one form and one 'save' button for the whole page
I hope this is clearer?
You don't need to have a specific controller for each controller, although I suspect you meant to say "I have created a method accepting POST in the RenderPartial's action ..."?
When you accept the default html helper commands, it can sometimes get confusing which action will be called. For a particular web page, the tag will determine where to POST values. So the action called will be dependent on the controller/action you specify in your Html.BeginForm call.
For example, here's a form we use from an ascx page:
<% using (Html.BeginForm("InvoiceDetail" //Action
, "CompanyInvoice" //Controller
, FormMethod.Post
, new { #id = "InvoiceForm", #autocomplete = "off" }))
{%>
A form can post to any action, in any controller. Not that you'd want to, but it's quite flexible. You can also have multiple forms in a single web page now, which is great for complex forms.
Related
I am asking this question to make sure myself that I understood the subject.
"The only way to have a submit button inside a partial view is using Ajax techniques to submit the form"
Well, technically you could do a normal postback from a partial view. But that would tend to defeat the point of a partial:
the entire page would have to be re-loaded, which means the result of the partial-view postback would need to be a complete page.
the partial view's modularity suffers, because the result of its postback falls out of the partial view's scope (ie, the partial view needs to know about the entire current page).
So, it's an irregular thing to do a non-AJAX postback from a partial view. But there are scenarios where it would be useful/appropriate. Consider for example a "login" partial: you may want to post the credentials back to a specific controller/action, and have that action redirect back to the current page. In that case you could reasonably use a non-AJAX form.
The only way to have a submit button inside a partial view is using Ajax techniques to submit the form
You didn't say where you got the quote from, but this isn't true.
You submit a form from a partial view in exactly the same way you submit a form within a main view. You can do this using custom fields or by making your partial view strongly typed. Where are you getting hung up?
Wasnt sure how to word the question, but this is the scenario:
the view is a data entry form eg http://127.0.0.1/User/AddEdit/
so edit the user I have an ID: http://127.0.0.1/User/AddEdit/7838fd9c-425c-4c98-b798-771bba10d9c1
This ID gets the data to populate the form values in a ViewModel, which populates the form
I am using jquery/ajax to save the form, which returns a Json result, indicating ok/error etc
In the View, I get the ID and use this in a hidden field which is set via jquery when the page loads and when the form is saved via ajax.
This seems a bit clunky, how do others do this?
in my opinion best solution is to create a partial view with all the fields and use it on add and edit view which are separate actions in controller. after you create user you can redirect to action edit. if you must / like use ajax you can reload div with form (change from user/add to user/edit/1). i might be wrong but i never see a code or example with one action in controller for add and edit.
I am writing a basic blogging application in ASP.NET MVC. I have a Post model which can be displayed via View.aspx. On that page I also want to have a form to submit a comment, but as View.aspx inherits the Post model, I don't know how to have it edit a Comment model.
In your controller you can use whatever model you like. So place a form in your view which points to Post/Comment/{postid} or Comment/Add/{postid}. After you added the model to the database redirect to the previous view.
tsv - create a few partialviews for the comments (strongly typed) and create a couple of methods on the comment controller:
GetComments(int postId)
AddComment(Comment newComment)
in your post view, call the partialview either via $ajax or directly in the page.
jim
The key thing to understand here is when your page 'inherits' a class (Post, in your case), this is purely so that the Model does not need to be cast in any way.
This does not restrict you from referring to other classes within the aspx page, nor does it prevent the page from having a form which posts to another Controller/Action that inherits from a completely different class (Comment, in your case).
Maybe if you posted some example code, we could suggest ways to make it work the way that you want.
As Jim said, you can create the necessary methods in a different or in the same Controller and call <% Html.RenderAction("methodName","ControllerName") %> in your view.aspx which will still inherit the Post Model.
Then, create usercontrols for the form to submit a comment and to display all the comments.
Rewritten: My original post seemed to be misunderstood. I have since reported it as a bug with the following description. My original post for this question can be found below the second <HR>.
I have a major issue with POST in a user control.
I have a UserControl which has a controller containing two ActionMethods called 'ContactForm'. The second has ActionVerb.POST on it to respond to the post-back. The user control is primarily used via AJAX - but that actually is irrelevant here. Obviously these action methods render a partial view.
I have a main page containing an additional html form for 'EnterContest'. Again - its controller has two ActionMethods called 'EnterContest', one of which responds to ActionVerb.POST. This view contains the 'ContactForm' in a side bar which is rendered with :
<% Html.RenderAction("ContactUsForm", "Company", new { commentsBoxHeader = "Questions" }); %>
The problem occurs when posting back the 'EnterContest' Form (the main form on the view).
The POST request from Fiddler contains just this query string (obviously not containing any of the POST data from the contact us form because thats a completely separate HTTP ACTION).
contestId=ND09&email=fred&btnEnterContest=Submit
(yes, this looks like a GET but thats
what Fiddler shows for a POST too)
First - (as expected) - the 'EnterContest(FormCollection data) method is called in the main controller. This processes the form submission to enter the contest - calls the webservice etc..
Second - (NOT expected) - The POST method of the 'ContactForm' controller is called. This immediately crashes because it is missing expected parameters - and we don't want it called anyway. This happens during the same Http request.
If I take a look at the stack trace - it is being called from the dynamically generated aspx page - originating at the Html.RenderAction line of code shown above. So obviously what is happening is the code that is looking to partially render the 'ContactUs' action method looks at the Request and sees there is a method to handle POST so it routes it there - which is VERY BAD. Its probably somewhere around this method in the framework :
System.Web.Mvc.dll!System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod
This behavior is VERY confusing and really breaks what seemed to be a simple page. I'm pretty sure it is a bug - because I cannot see an elegant work around without some really clumsy checking in my controller. I think RenderAction is in futures - but I don't know if the issue is present there or in the main framework.
Just to clarify what is NOT happening :
any clever jQuery
more than one HTTP request (verified in Fiddler)
nested forms
Thanks
Original post
I am using the RenderAction Html extension in ASP.NET MVC.
I came across something unexpected, but which is making more sense as I think about it.
Lets say I have a view containing a 'RenderAction' method to generate the contact for a part of the page.
<% Html.RenderAction("ContactUsForm", "Company",
new { commentsBoxHeader = "Questions" }); %>
In this case the partial view it generates creates an ajax form which posts back via <%= Html.BeginAjaxForm() %>.
So of course I need an actionresult to handle the AJAX postback.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ContactUsForm(FormCollection formdata)
Now the problem occurs when the parent view containing this partial render action has a normal (non-ajax) form with a POST action. What happens is that the POST method for the ContactUsForm action is call in addition to the POST action for the main view. Inside this action the formdata property contains all the properties for the parent view - so ContactUsForm dies with a null reference or something like that.
I've come up with 3 possible solutions :
1) create a different action name for the post back for any user controls on the page. This has the disadvantage that you have to post back to a different function than created the partial view. Often this can be more cumbersome but this is what i'm doing right now.
2) check in every POST method (you'd have to remember to run this check in every user control's POST action method) to see if the form data is intended for that form it, and if not return a default view.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResultContactUsForm(FormCollection formData)
{
if (formData["btnSubmitContactUsForm"] == null) {
// "This form is not for us!";
// figure out how (if is possible) to return the get default view here
// and call it with the right arguments
}
}
3) report it as a bug.
What should I be doing here? I'm leaning towards thinking of this as a bug
Edit: One very important thing I need to stress more is that BOTH POST methods are called - so its not just somethig like a nested form.
Edit 2: In Fiddler I see only one request. The problem is when it tries to render the ContactUsForm after having already handled the POST for my main page it hits the 'POST' method for 'ContactUsForm' instead of the non-post handler.
EDIT2: I just noticed that you are using RenderAction instead of RenderPartial. I suspect what is happening is that it is using the RequestContext of the posted form to choose which ContactUsForm method to choose when the RenderAction is invoked. This is arguably correct behavior since the action is being invoked from a postback, just not the one you intended. I would approach this in a completely different manner. Have the partial generated by a ViewUserControl and include it on the page using RenderPartial instead. Remove the GET ContactUsForm method and only have the POST version. That is, the form itself is generated as a ViewUserControl with markup predetermined or dynamically generated via parameters passed via ViewData. The form response is handled via the controller action.
EDIT: Since you indicate that nesting is not the issue, is it possible that you are using javascript (say jQuery) to trigger the submit and your selector is too broad. If, for example, you had code like the following, that would account for the behavior you are seeing.
$(document).ready( function() {
$('#mybutton').click( function() {
$('form').submit();
});
});
Original answer: (left for context)
It sounds like you have nested forms in your view. Try moving the RenderAction outside the form in the parent view and see if that fixes your problem. My feeling about forms in MVC views is that they should be compact and only cover the markup that contains the actual inputs. This is a change from WebForms where you typically wrap all of your mark up within the form. Use CSS to control layout if you need to have the form elements appear to be intermixed.
This is actually a confirmed bug both in ASP.NET MVC 1.0 with MVC Features library and in ASP.NET MVC 2.0.
RenderAction behaves incorrectly when the request is POST.
I have submitted the bug in ASP.NET Issue Tracker on Codeplex, please vote for it :)
http://aspnet.codeplex.com/WorkItem/View.aspx?WorkItemId=5847
I am wondering if there is a way to make ASP.NET controls play nicely with my ASP.NET MVC app. Here is what I am doing.
I have an order page which displays info about a single Order object. The page will normally have a bunch of rows of data, each row representing an OrderItem object. Each row is an ASP.NET User Control. On the user control there is a form element with two text boxes (Quantity and Price), and an update button.
When I click the update button, I expect the form to post the data for that individual OrderItem row to a controller method and update the OrderItem record in the database.
Here is my problem: When the post happens, the framework complains because the fields on the form don't match the parameters on the controller method. Each form field is something like "OrderItem_1$Quantity" or "OrderItem_2$Price" instead of just "Quantity" or "Price" which would match my method parameters.
I have been told that I can overcome this by making sure that the IDs of all my controls are unique for the page, but allow the NAMEs to be repeated between different forms, so that if a form for an individual row is posted, the name can be something that will match what is on my controller method.
The only problem is that I am using ASP.NET controls for my text boxes (which I REALLY want to continue doing) and I can't find any way to override the name field. There is no Name propery on an ASP.NET control, and even when I try to set it using the Attributes accessor property by saying "control.Attributes["Name"] = "Price";" it just adds another name= attribute to the HTML tag which doesn't work.
Does any one know how I can make this work? I really don't like all of the HtmlHelper functions like TextBox and DropDown because I hate having my .aspx be so PHP or ASP like with the <%%> tags and everything. Thanks!
I think you're straddled between two worlds of ASP.NET WebForms and ASP.NET MVC. You really need to use the Html.TextBox methods, etc. in MVC. This gives you complete control over the markup, which is one of the main benefits of MVC.
The very problem you're having with control over the generated HTML, e.g. getting two name attributes, is exactly what MVC is designed to address. If you stop fighting it and go with the flow, it'll work much better.
<% %> tags aren't a problem unless you have logic in there. Putting simple presentation logic on your view is fine.
If you don't like this, then maybe it's better to stick with standard ASP.NET.