How to define Html.BeginForm for action with attribute routing? - c#

Controller
[HttpGet]
[Route("~/search/{clause}/{skip?}")]
public async Task<ActionResult> Search(string clause, int skip = 0)
{
...
}
View
#using (Html.BeginForm("Index", "search", FormMethod.Get))
{
#Html.TextBox("clause", null, new { #class = "form-control col-md-4" })
...
}
Rendered Html
<form action="/search" method="get">
<input id="clause" name="clause" type="text" value="test">
</form>
I am using [HttpGet] partly because i want the search to be accessing via http://myapp.com/search/<search values>
When i navigate to http://myapp.com/search/test, everything seems fine, but when i try to enter my new search term in the textbox and hit enter or submit, it navigates to http://myapp.com/search?clause=newsearch
What should I do so that my textbox will navigate to http://myapp.com/search/newsearch instead?

Your form generates http://myapp.com/search?clause=newsearch because a browser has no knowledge of your routes (c# code running on your server).
In order to generate your preferred url (http://myapp.com/search/newsearch), you need javascript to intercept and cancel the default submit, and build a url to navigate to. Using jQuery:
$('form').submit(function() {
var baseUrl = $(this).attr('action'); // or var baseUrl = '#Url.Action("Index", "search")';
var url = baseUrl + '/' + $('clause').val(); // add value for skip if required
location.href = url; // redirect
return false; // cancel the default submit
});

Related

MVC, how to post data to controller and redirect to aspx page

I have an MVC view where user can set a flag and post data to controller (post because I want to hidden query string)
After the controller have done his job I want to redirect to website home page that is an aspx page (my site is mixed aspx and MVC)
Is there a way to do that?
This is my view
#model MessaggiVM
<form role="form" class="form-inline" method="post" action="Messaggi/VaiAllaHome">
<button id="btnHome">Vai alla pagina iniziale</button>
<div class="form-group">
<label for="nascondi">hiding</label>
<input id="nascondi" type="checkbox" name="nascondi" value="true" />
</div>
<input type="hidden" name="elencoPost" value="#Model.Posts" />
#*#Html.ActionLink("Messaggi", "VaiAllaHome", new { posts = Model.Posts} )*#
</form>
And this the controller
[HttpPost]
public RedirectResult VaiAllaHome(bool? nascondi = false, IEnumerable<Messaggio> elencoPost = null)
{
// do something
return Redirect(Url.Content("~/"));
}
When I run this code controller action is executed without error but redirect is not done and browser remain on the view
Other problem is that elencoPost parameter is empty in the action but I'm investigating it
EDIT
Honestly I'm thinking to post data on input change and switch button for a simply link
EDIT 2:
found the reason: in default.aspx i have a auto-redirect to Message page :(
Try
return Redirect("~/home.aspx");
or
return Redirect(Url.Content("~/home.aspx")
You should be able to use Redirect with a relative url:
[HttpPost]
public RedirectResult VaiAllaHome(bool? nascondi = false, IEnumerable<Messaggio> elencoPost = null)
{
// do something
return Redirect("/home.aspx");
}
Try using a #Url.Content on your form tag
<form action="#Url.Content("~/Messaggi/VaiAllaHome/")">
Then in your Controller
[HttpPost]
public RedirectResult VaiAllaHome(bool? nascondi = false, IEnumerable<Messaggio> elencoPost = null)
{
// do something
return View(Url.Content("~/"));
//return RedirectToAction("Action", "Controller", new { routeParameter = value } /*e.g. "id = 1"*/);
}

How to open new window from MVC Controller?

This is my code
public ActionResult Contact()
{
//var getRequest = (HttpWebRequest)WebRequest.Create("https://brisol.net/av-d");
//var getResponse = (HttpWebResponse)getRequest.GetResponse();
//return new HttpWebResponseResult(getResponse);
return ExternalGet("https://sample.net/av-d");
}
/// <summary>
/// Makes a GET request to a URL and returns the relayed result.
/// </summary>
private HttpWebResponseResult ExternalGet(string url)
{
var getRequest = (HttpWebRequest)WebRequest.Create(url);
var getResponse = (HttpWebResponse)getRequest.GetResponse();
return new HttpWebResponseResult(getResponse);
}
In the above code when i click contact link it open the below url with in the same window,but i want to open new window from mvc controller.
You can use target for blank page
HTML Code
<input type="button" target="_blank"/>
MVC Code
#Html.ActionLink(" ", "ActionName", "ControllerName", null, new { target = "_blank", #class = "btn btn-primary fa fa-list"})
That is not an issue of the MVC. It depends on your HTML code. The link which should be opened in a new window should look like this:
Click me
Please, notice the target attribute. However, keep in mind that it is up to the browser whether it opens new window or just a new tab.
Things like that should be done from the view or from javascript not from the controller.
javascript:
window.open("Link URL")
razor
#Html.ActionLink("bla", "Action", new {controller="Controller"}, new {target="_blank"})
or
bla
New tab/window can be controlled from your html page actually, not from server side code.
Use target='_blank' attribute in your anchor (<a>) tag.
If you are using plain HTML, do:
MDN
For rajor helper, do
#Html.ActionLink("visit the page", "action", "controller", new {target="_blank"})
Here is the help page:
https://developer.mozilla.org/en/docs/Web/HTML/Element/a
Dim strScript As String = "window.open('../Newpage.aspx', 'new_window');"
Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), "Open window", strScript, True)
Below Code will help you
Controller:-
public ActionResult ABC()
{
if(Request.HttpMethod == "POST")
return Redirect("http://www.google.com");
else
return View();
}
View:-
#using (Html.BeginForm("ABC", "Test", FormMethod.Post, new { target = "_blank" }))
{
<input type="submit" value="Contact" id="btnsubmit" />
}
Above example is just give you idea how to open new url from the controller you need to set this idea in your code.
In this example controller is Test , when you post the request like click on Contact then post the view with target = “_blank” so response of the controller action will be open in new window.

Pass values from Hidden field to ActionLink then to Controller

I'm trying to dynamically set the StudentIds by letting the user select check boxes for the reports they want. When they click the ActionLink, I use jQuery to set the values of the ids in a hidden field. I need the Action Link to read the ids from hidden field.
The values are getting set in the hidden field, but they are not being passed to the controller from the actionLink.
I need to pass the ReportIds to the controller.
#Html.ActionLink("PrintMed", "GetMedEdVerificationReport", "Student", new { studentIdList = Model.ReportIds }, new { #class = "button print_selected print_selectedMedEd disabled" })
#Html.HiddenFor(model => model.ReportIds)
javascript
$('.print_selectedMedEd').bind('click', function () {
var ids = getPrintIds();
if (ids.length == 0) {
return false;
}
$('#ReportIds').val(ids.toString());
return true;
});
When the asp.net mvc render your ActionLink it will generate a link with a parameter that you have on the model. Event you change the value of the model, it will not change the value on the output generated by ActionLink.
Given this, you have to se again the value, try to generate an ACtionLink without the argument:
#Html.ActionLink("PrintMed", "GetMedEdVerificationReport", "Student", null, new { #class = "button print_selected print_selectedMedEd disabled" })
On the javascript side, you could try using the on method to bind a event handler and call the preventDefault method from the event argument, for sample:
$('.print_selectedMedEd').on('click', function (e) {
e.preventDefault();
var ids = getPrintIds();
if (ids.length > 0) {
$('##Html.IdFor(model => model.ReportIds)').val(ids.toString());
// make an url to redirect
var url = $(this).prop("href") + "?studentIdList=" + ids.toString();
// redirect using the generated url
window.location.href = url;
}
});
Remember to use the Html.IdForm() to make sure you have the right id for a specific property.
That is because #Html.ActionLinkdoesn't use the hidden fields to make the request. Once the action link renders it becomes
PrintMed
so you would need to modify the html on the anchor tag.
You should be using Html.Beginform instead in order to pass along the model.
#using (Html.BeginForm("GetMedEdVerificationReport", "Student", FormMethod.Post, null))
{
#Html.HiddenFor(model => model.ReportIds)
<input type="submit" value="PrintMed" />
}
#Html.HiddenFor(modelItem => item.OrderId)
<td>
<input type="button" value="Pickup" onclick="location.href='#Url.Action("Edit", "Assignment", new { ID = item.OrderId })'" />

Transform Querystring to RouteValue in Razor View

I'm stuck with a very basic detail in a view.
I want to be able to let the user filter the results in the Index view.
To do this I've created a dropdown list, which gets populated thourgh my viewmodel:
#using (Html.BeginForm("Index", "Captains", FormMethod.Get)) {
<div class="row">
<div class="dropdown">
#Html.DropDownList("Name", new SelectList(Model.SomeProperty), new { id = "FilterList" })
</div>
</div>
#* ... *#
}
Additionally I have a small jQuery snippet to submit the form on the change event:
$('#FilterList').on('change', function () {
var form = $(this).parents('form');
form.submit();
});
The route I have created for this looks like this:
routes.MapRoute(
name: "IndexFilter",
url: "{controller}/{action}/{Name}",
defaults: new { Name = UrlParameter.Optional}
);
After the submit event I get redirected to the url /Index?Name=ChosenValue
This is filtering totally correct. However I'd like to get rid of the querystring and transform the route to /Index/ChosenValue.
Note: "Name", "ChosenValue" & "SomeProperty" are just dummy replacements for the actual property names.
Instead of submitting the form, you can concatenate /Captains/Index/ with the selected value of the dropdown and redirect to the url using window.location.href as below
$('#FilterList').on('change', function () {
window.location.href = '/Captains/Index/' + $(this).val();
});
I think you're looking for the wrong routing behavior out of a form submit. The type of route resolution that you're hoping to see really only happens on the server side, where the MVC routing knows all about the available route definitions. But the form submission process that happens in the browser only knows about form inputs and their values. It doesn't know that "Name" is a special route parameter... it just tacks on all the form values as querystring parameters.
So if you want to send the browser to /Index/ChosenValue, but you don't want to construct the URL from scratch on the client, you need to construct the URL on the server when the view is rendering. You could take this approach:
<div class="row">
<div class="dropdown">
#Html.DropDownList("Name", new SelectList(Model.SomeProperty),
new {
id = "FilterList",
data_redirect_url = #Url.Action("Index", "Captains", new { Name = "DUMMY_PLACEHOLDER" })
})
</div>
</div>
Above you're setting the URL with a dummy "Name" value that you can replace later, then you'll do the replacement with the selection and redirect in javascript:
$('#FilterList').on('change', function () {
var redirectUrl = $(this).data('redirect-url');
window.location.href = redirectUrl.replace("DUMMY_PLACEHOLDER", $(this).val());
});
If you are wanting to drop the query string off the url because it looks weird, then change your FormMethod.Post.
However, to really answer your question, I've tried the following successfully (Note: this might be considered a hack by some)
In short: update the action url on the form element when the list changes, client side.
$('#FilterList').on('change', function () {
var form = $(this).parents('form');
var originalActionUrl = form.attr("action");
var newActionUrl = originalActionUrl + "/" + $(this).val();
form.attr("action", newActionUrl);
console.log(form.attr("action"));
form.submit();
});
You will need to change your controller's signature to match whatever optional param value you specify in your route config. In your example, "Name".

Need uploadcontrol in a ajax.beginform using asp.net mvc3 html5 razor

I've been looking for a long time for this but I'm still stuck, I need to have an upload control where the user can upload a document and give additional information.
I've had to do this before without the upload control so what I do is I get an ajax.beginform that will give all the input from the user to the controller and than close the popup trough a onsucces function, so this looks like this:
view:
#using (Ajax.BeginForm("Save", "Documents", new AjaxOptions { HttpMethod = "Post", OnSuccess = "CloseDialog" }, new { #class = "form-inline", id = "FormId" }))
{
#Html.Label("Description", "Description")
<div class="span3">
#Html.TextBoxFor(m => m.Description)
</div>
}
I tried adding there an Html.BeginForm but then I found out that it is not possible to use nested forms so I deleted this.
In my controller I have:
public PartialViewResult Index(string description)
{
var model = new DocumentsModel{ Description = description};
return PartialView(model);
}
[HttpPost]
public ActionResult UploadFile(HttpPostedFileBase file, string description)
{
if (file != null && file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath(#"D:\Documentds\"), fileName);
file.SaveAs(path);
}
return RedirectToAction("Index", new { description = description });
}
Ofcourse because the html.beginform won't work this controlleraction won't work either
So my question is how to do this without having to use a html.beginform?
You need to have the file upload inside the form and also the enctype="multipart/form-data" property on the form that calls uploadfile. That could be one problem.
Also, you could use JavaScript to submit the form you want from another part of the page without having them nested and keeping your design.

Categories