Pavel
Pavel

Reputation: 153

Add parameters to the form in razor

I have this form in my view which leads me to some action in the controller. The thing is I don't know how to pass parameters to the action method.

<form class="full-search" asp-controller="Movies" asp-action="Search">
    <input type="search" name="searchmovie" placeholder="Search..." class="search-form">
    <select name="option" form="">
        <option name="option" value="category1">category 1</option>
        <option name="option" value="category2">category 2</option>
        <option name="option" value="category3">category 3</option>
    </select>
    <i class="fas fa-caret-down"></i>
    <input type="submit" name="" class="submit-full-search">
    <div class="search-btn-submit">
        <img src="~/img/search.svg">
    </div>
</form>

And this is my controller:

[HttpGet("searchmoview/{option?}/{searchmovie}")]
public  IActionResult Search(string option, string searchmovie)
{
    //perform some search based on the filters
    return View("Search", data);
}

But when I run my code, when I click on search the url looks like this:

https://localhost:33590/Information/Search

Instead of like this:

https://localhost:44320/seachmovie/category1/{searchString}

Any idea guys on how can I pass the parameters?

Upvotes: 3

Views: 10243

Answers (2)

Kevin Suarez
Kevin Suarez

Reputation: 71

Long story short - there is no out of the box way of mapping form values to a route.

The best way to pass values back to your mvc controllers is to have a view model.

Create a search view model.

//View Model
public class SearchViewModel{
    public string Query {get;set;}
    public string Category {get;set;}
}

In your controller you'll want to pass this down to your view or partial view. Use "ActionResult" in .NET and "IActionResult" in .Net Core

//Controller
public class SearchController{
    [HttpGet]
    public ActionResult SearchBox(){
        return View();
    }


    [HttpPost]
    public ActionResult SearchBox(SearchViewModel model){
        //model is now populated with your values from your form.
        //ex: model.Query

        return View();
    }
}

Create an enum for your categories, there is many other ways to do this but this one is the simplest.

//Enum
public enum Categories
{
    Category1,
    Category2    
}

Now in your razor view bind your view model and you're good to go.

//Razor View
@model SearchViewModel

@using (Html.BeginForm("SearchBox", "Search", FormMethod.Post))
{

    @Html.TextBoxFor(x => x.Query, new { @class = "search-form"})
    @Html.DropDownListFor(x => x.Catergory,
                    new SelectList(Enum.GetValues(typeof(Categories))),
                    "Select Category", new { @class= "example-class"})
    <i class="fas fa-caret-down"></i>

    <input type="submit" name="" class="submit-full-search">
    <div class="search-btn-submit">
        <img src="~/img/search.svg">
    </div>
}

If you want the form values to be posted to your url you can change it to FormMethod.Get

//Razor View
@model SearchViewModel

@using (Html.BeginForm("SearchBox", "Search", FormMethod.Get))
{

    @Html.TextBoxFor(x => x.Query, new { @class = "search-form"})
    @Html.DropDownListFor(x => x.Catergory,
                    new SelectList(Enum.GetValues(typeof(Categories))),
                    "Select Category", new { @class= "example-class"})
    <i class="fas fa-caret-down"></i>

    <input type="submit" name="" class="submit-full-search">
    <div class="search-btn-submit">
        <img src="~/img/search.svg">
    </div>
}

If you change it to get, you'll also have to change your controller to expect these in your get method. You can also just bind the model and MVC will map the parameters back into the model for you automatically.

public class SearchController{
    [HttpGet]
    public ActionResult SearchBox(SearchViewModel model){
        //if the model values are in the URL "model" will be populated, else it will be null.
        return View();
    }
}

Upvotes: 3

Chris Pratt
Chris Pratt

Reputation: 239290

You can't. That's not how things work. A form will by default send a POST request, in which case inputs in the form are sent as part of the request body (i.e. not the URL). You can set the method to GET, instead, but then the input values will be sent as part of the query string (i.e. ?foo=bar), not as part of your path, as you're looking for.

The only way to remotely achieve what you want is to use JavaScript to manipulate the form's action based on things like the category select box changing. You'd bind to the change event of that element, and then you'd alter the form element's action attribute in some way.

Upvotes: 1

Related Questions