Marco
Marco

Reputation: 23945

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.

Upvotes: 0

Views: 63

Answers (3)

TSmith
TSmith

Reputation: 543

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".

Upvotes: 0

jdmcnair
jdmcnair

Reputation: 1315

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());
});

Upvotes: 1

ekad
ekad

Reputation: 14624

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();
});

Upvotes: 1

Related Questions