I have a simple partial with a form inside which is used as a search bar.
#using (Html.BeginForm("Details", "Projects", FormMethod.Get))
{
<div class="row" style="margin-bottom: 20px;">
<div class="col-lg-3 pull-right">
<input type="search" class="form-control" placeholder="Search Code" id="projectSearch" name="code" />
</div>
</div>
}
This should post to my Projects Controller Details Action, however this isn't happening, and I believe this because of the [Route] attribute that is applied to the action, as when I comment this out, the form posts correctly. However I want to use the [Route] attribute.
The action looks like this:
[HttpGet]
[Route("{code}/Details")]
public ActionResult Details(string code)
{
if (code == null)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
...
return View(viewModel);
}
When the attribute is in use the form will post to this url:
/Projects/Details?code=PP61
which doesn't map to the correct action. Instead I get a resource cannot be found error.
The expected/desired url should look like
/Projects/PP61/Details
This works fine if I create a Url.Action or browse to the URL, so I know this action works, however it doesn't work with a form post. Any ideas why?
Thanks.
Change [HttpGet] to [HttpPost] on the controller and FormMethod.Get to FormMethod.Post in the view.
I have one solution to the problem, it doesn't however answer why this wasn't working in the first place. I have created a separate action which is for the search bar to POST to, this action then redirects to the GET action which I was trying to reach in the first place.
[HttpPost]
public ActionResult ProjectSearch(string code)
{
if (code != "")
{
return RedirectToAction("Details", new { code });
}
else
{
return RedirectToAction("Index");
}
}
This now works correctly, but I would still love to know why this didn't work to begin with if any body has any ideas. Cheers.
Related
I created a web app form using Google Apps Script and the HTMLService.
It is a one-page form with a submit button at the bottom.
When submitted, the form validates whether the data input into the form is valid, and if valid, it logs the form data to a spreadsheet.
That all works so far.
I now need the user to be sent to a confirmation page, and the confirmation page needs to be able to have parameters passed to it (to display certain information on the confirmation page).
main.gs:
function doGet(e) {
var template = HtmlService.createTemplateFromFile('form');
return template.evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function processFormSubmission(formData) {
Logger.log('starting processPoRequest');
Logger.log('po: ' + JSON.stringify(formData, null, 2));
// code for appending data to sheet here
}
form.html:
<!DOCTYPE html>
<form id="form1" name="form1">
<label for="info" id="info_label">Info</label>
<input id="info" name="info" type="text">
<input class="btn" id="button" onclick="onClickFunctions(document.getElementById('form1'))" type="submit" value="Submit">
</form>
<script>
function onClickFunctions(formData) {
console.log('starting onClickFunctions');
var allDataValid = validateForm(formData);
if (allDataValid === true) {
google.script.run.withSuccessHandler().processFormSubmission(formData);
}
}
function validateForm(form) {
console.log('starting validateForm');
var errors = 0;
var element = document.getElementById('info');
if (!form.info) { element.classList.add("validation_error"); errors++; if (errors === 1) element.focus(); }
else element.classList.remove("validation_error");
if (errors > 0) return false;
else return true;
}
</script>
confirmation.html:
<!DOCTYPE html>
<?!= confirmationMessage ?>
I don't know what to put in .withSuccessHandler() to make it so that the user is brought to the confirmation page.
I've Googled this extensively and found these results on Stack Overflow, and each one suggests a different solution, but none of them actually include complete working code for a solution:
Possible solutions using doPost:
Send form by email and track responses in spreadsheet
HtmlService doPost With Google Docs Form
HtmlService doPost
I messed around with doPost but I couldn't figure out how to get it to be invoked, and I couldn't find any official documentation in the HTMLService docs.
Possible solution using the link to the web app in an a href:
href in HtmlService
If my button was a link that looked like a button, I'm not sure how I would execute the form validation function when the link is clicked.
I have done this two different ways.
had a hidden statement that gets shown, and the form gets hidden.
or
use .withSuccessHandler(google.script.host.close()), but have the processFormSubmission function open a new dialogue.
Problem:
In my application I have provide the user a selection screen for something in several places (that is, the same selection screen has to be used in several actions).
Solution:
I've come up with the following solution: pass the return action and controller to action which handles the entity selection.
Example:
Suppose that there are several places in the application where the user has to select an instance of SomeEntity, so I added the following action to that entity controller:
public class SomeEntityController : Controller
{
/* ... */
public ViewResult Select(string returnAction, string returnController)
{
var selectableEntities = ...;
return View(
new SelectionViewModel<SomeEntity>
{
Entities = selectableEntities,
ReturnAction = returnAction,
ReturnController = returnController,
});
}
}
In the view for that action (Views/SomeEntity/Select.aspx) I put something like this:
<table>
<tr>
<th>Select</th>
<th>SomeProperty<th>
</tr>
<% foreach (var entity in Model.Entities) { %>
<tr>
<td>
<%: Html.ActionLink("Select", Model.returnAction, Model.returnController, new { entityId = entity.id }) %>
</td>
<td><%: entity.SomeProperty %></td>
</tr>
<% } %>
</table>
Then, if I need the user to select a SomeEntity in other controller I can do this:
public class OtherController : Controller
{
public ActionResult SelectSomeEntity()
{
return RedirectoToAction("Select", "SomeEntity", new { returnAction = "ActionThatNeedsAnEntity", returnController = "Other" });
}
public ActionResult ActionThatNeedsAnEntity(int entityId)
{
// here I can use the selected entity
}
}
The last piece of code is just an example of how to use the SomeEntity selection action. Instead of the SelectSomeEntity action, there could be a more complex action which performs some checks to see if an entityId is already selected (e.g. stored in the session) and then decide whether to call SomeEntity/Select or not
Question:
The above works fine, but I’m new to ASP.Net MVC 2 so I don’t know if there is other (standard) solution for this.
Is this approach correct/neat? Have you solve this same situation differently?
I could be misunderstanding your problem, but I think that Partial Views would be the "standard" solution you're looking for.
Partial Views are just that, small views that can be inserted into other views. Things like entry forms or displays of data can be put into a partial view and added to the regular view. They greatly simplify code.
They're simple to make. When you go to make a regular view, just check the "partial view" box in the window (i. e. after right-clicking in the solution explorer and selecting the "add view" option). You can then throw this into any full view by using <%: Html.Partial("myPartialView") %>. You can easily pass a Model to the partial view as well by doing <%: Html.Partial("myPartialView", Model) %>
I have a masterpage on which i displays groups that user can access now i want to gets its selected value in many controllers for saving with the records. I want to know if it is possible in asp.net mvc 2 and if not then what is the way around for it
What you are trying is possible and there are different techniques to achieve it. The best approach would depend on how you are invoking your controller actions. Whether you are using normal hyperlinks, submitting standard <form> or using AJAX. So if you are using standard action links you could add some javascript which binds to the onclick event of each link and adds the selected value of the group. Example:
$(function() {
$('a').click(function() {
// everytime a link is clicked
// add the value of the selected group to the url
var selectedGroup = $('#IdOfYourDdl').val();
if (this.href.indexOf('?') > 0) {
window.location = this.href + '&selectedGroup=' + selectedGroup;
} else {
window.location = this.href + '?selectedGroup=' + selectedGroup;
}
// cancel the default action as it doesn't contain the selectedGroup
// parameter in the request
return false;
});
});
and in your controller action you could have this additional parameter:
public ActionResult Foo(string selectedGroup)
{
...
}
Another example is if you use AJAX you could setup a default data in the master page which will ensure that the value of the dropdown will be sent along each AJAX request you are performing:
$.ajaxSetup({
data: { selectedGroup: $('#IdOfYourDdl').val() }
});
Now whenever you send an AJAX request to your server:
$.get('/foo', { someParam: 'someValue' }, function(result) {
});
the following request will be sent: /foo?someParam=someValue&selectedGroup=123 so you will be able to fetch the value of the selected group back in the controller action.
I hope I understand your question since no code-example is supplied.
You can do this using a viewmodel on the page which contains your display groups. Another option is to get the value from the FormCollection when the page is posted.
For example:
public ActionResult MyAction(MyViewmodel viewModel)
{
//value from your viewmodel, strongtype
var value = viewModel.group;
}
OR
public ActionResult MyAction(FormCollection collection)
{
//value as a string
var value = collection.getValue("MyKey").AttemptedValue;
}
If this answer doesn't statisfy you then please be more clear in your question and i'll try to help you further.
As long as your drop down list is a descendant of the <form> that is submitted, it will be subjected to standard model binding, which means you can include it as a parameter on your action. Ensure the name attribute of the drop down list matches the name of the action parameter.
Final rendered HTML:
<form action="http://.../MyAction" method="post">
<select name="dropDownList">
<option value="a">Option A</option>
<option value="b">Option B</option>
...
</select>
...
</form>
Controller:
[HttpPost]
public ActionResult MyAction(string dropDownList, MyActionModel model)
{
// dropDownList = value attribute of selected <option>
...
}
I'm pretty new to MVC 2 and I'm having problems figuring out how to post values that lies outside the form.
This is my code very simplified:
<input type="text" id="TextboxOutsideForm"/>
<% using (Html.BeginForm("Edit", "Home", FormMethod.Post)) {%>
<%: Html.ValidationSummary(true) %>
<%: Html.TextBoxFor(model => model.Stuff) %>
<input type="submit" value="Save" />
<% } %>
TextboxOutsideForm can be changed by the user and when pushing save I want to include the value from this control to the action in the controller. It would also be great if i could use model binding at the same time.
This would be great:
[HttpPost]
public ActionResult Edit(int id, Model model, string valueFromTextbox)
Or just a FormCollection and a value..
I know that in this simplified example i could just put the textbox inside of the form, but in real life the control is 3rd party and is creating loads of of other stuff, so i just need to grab the value with jquery maybe and post it..
Is this possible?
Thanks
you can have a look at this question that explains how to dynamically create the form and submit it. you can hijeck the submit event and add value into form dynamically
$(function() {
$('form').submit(function() {
$(this).append($("#ValueOutsideForm"));
return true;
});
});
this way u don't have to rely on ajax and u can post ur form synchronously.
If you use a normal form post only inputs inside the form will be sent to the server. To achieve what you are looking for you will need to submit the form using AJAX. Example:
$(function() {
$('form').submit(function() {
$.ajax{
url: this.action,
type: this.method,
data: $(this).clone().append($('#TextboxOutsideForm').clone()).serialize(),
success: function(result) {
alert('form successfully posted');
}
});
return false;
});
});
Also don't forget to give a name to the input field which is outside the form.
I have a masterpage that render's the following PartialView:
<% Html.RenderPartial("AddPage); %>
AddPage Controller looks like this:
public class PagController : Controller
{
[HttpGet]
public PartialViewResult AddPage()
{
return PartialView();
}
[HttpPost]
public PartialViewResult AddPage(FormCollection forms)
{
//some logic here
// some view data here
return PartialView();
}
}
And the view looks like this:
<% using (Html.BeginForm("AddPage", "Page", FormMethod.Post, new { ID = "PageManager" })){%>
<%= Html.TextBox("txtAddPage") %>
<input type="submit" value="AddPage" />
<%} %>
My issue is, that when i hit submit i get redirect to : http://localhost:1234/Page/AddPage, when instead i just want the partialview to be submitted, and return some basic view data if needed, as well as stay on the same page.
Am i having a blonde moment here? cause i know i have done this before
EDIT - This partial view is rendered in multiple pages, not just one.
Fullpage postback solution
This is a bit tricky since you have to know where to go back. I suggest you change your view and add two additional hidden fields (or one and parse its value - as you wish) and store current controller/action values in it.
You can then use this data in POST action to return a RedirectResult like:
return RedirectToAction("action_from_field", "controller_from_field");
Ajax postback solution
You can always submit your data using Ajax in which case your postback URL can be anything you want. In your case it should be to the current page URL. Edit: And Ajax would be the preferred solution in your particular case.
If you want to submit and only reload part of your page, you'll need to use AJAX. The most basic way to do this would be to render the partial view in an UpdatePanel.