6

I have a view that contains a Google map with a default zoom level and position set on a country. The default position to show on the map comes from DB and what I do is that I have a [HttpGet]Index action that fetches this information, sends it to the view and then in the view I use JS to draw the map (just usual google map stuff to draw a simple map).

Then just above the map div, I show a textbox and a search button. So the user types in an address and presses the search button, I post the value of textbox to a [HttpPost]Index action. Now I want to pass this value to [HttpGet]Index action so that it goes and fetches data from DB for that address, send it to the Index view so that the map is redrawn with that particular address set as the center of the map and showing the address in the textbox as well.

Any suggestions on how can I do this?

The way I have tried (and it didn't work) is to call the Get version of Index action and pass the address to it by using TempData dictionary. But all i see is an empty/blank page.

Here is how my HttpGet Index action looks:

[HttpGet]
public async Task<ActionResult> Index()
{
    // I fetch the info from DB here put it inside ViewBag and call the view    
            return View();
}

This loads the info correctly and the map is drawn as it should when the URL controller/Index is hit first time in the browser.

The markup for the textbox and search button is:

<form class="form" id="searchForm" action="@Url.Action("Index", "Default")" method="post">
<div class="form-group">
    <div class="row">
        <div class="col-xs-9 col-sm-9 col-md-10">
           <label for="address" class="sr-only">Search for address</label>
           <input type="text" class="form-control" id="address" placeholder="Search for address" name="address">
         </div>
    <div class="col-xs-3 col-sm-3 col-md-2">
    <input type="submit" class="btn btn-block btn-success" value="Search" />
    </div>
   </div>
</div>
</form>

and finally here is the HttpPost Index action:

[HttpPost]
public void Index(String address)
{
   TempData["address"] = address;
   Index();
}

So when I submit the form, I want that it gets posted to the HttpPost Index action and then it passes the value to the HttpGet version of it which will eventually get data from DB and get the view with updated map. But all I see is a blank page.

Any help?

Syed
  • 329
  • 2
  • 6
  • 18

2 Answers2

12

like that

[HttpPost]
public void Index(String address)
{
   TempData["address"] = address;
   RedirectToAction("Index");
}

you see it blank because you are redirecting RedirectToAction("Index"); and storing data in TempData and u r not using it in the index Get method

[HttpGet]
public async Task<ActionResult> Index()
{
    // I fetch the info from DB here put it inside ViewBag and call the view   
    // you must check for the temp data
    if (!string.IsNullOrWhiteSpace(TempData["address"].ToString()))
    {
         ViewBag["result"] = TempData["address"];
         //and use you viewbag data in the view
    }
    return View();
}
Sherif Ahmed
  • 1,896
  • 1
  • 19
  • 37
  • Thanks Sherif. But I still see a blank page. – Syed Apr 16 '15 at 12:49
  • I will tell u why u see a blank page – Sherif Ahmed Apr 16 '15 at 12:50
  • Thanks. I am waiting! – Syed Apr 16 '15 at 12:52
  • I am using it. ViewBag.RawAddress = TempData["Address"] in Index Get method. – Syed Apr 16 '15 at 12:59
  • but all over this is a bad approach ... you can read more about Post Redirect Get mechanism ... u can check [THIS](http://stackoverflow.com/q/5538005/2907017) && [THIS](https://www.stevefenton.co.uk/Content/Blog/Date/201104/Blog/ASP-NET-MVC-Post-Redirect-Get-Pattern/) – Sherif Ahmed Apr 16 '15 at 13:00
  • I am using it like this: ViewBag.RawAddress = TempData["Address"]; instead of your ViewBag["result"] = TempData["address"]; – Syed Apr 16 '15 at 13:02
  • I a reading your links which you have suggested. But in the mean while I have a question that how could "not" using TempData in Get Index method result in a blank page at all?? I mean why don't I see the other layout and style of the page at least? – Syed Apr 16 '15 at 13:20
  • Article in first link does not solve anything in my case. It was read from having a knowledge about it point of view. Article in the second link is a little different than my case. He is "Fetching" some values in Get method while "Saving" some values in Post method. In my case, I need to send an address to Post and it will actually do the same thing as Get method does. So that's why I want to call Get Index method to avoid code duplication. – Syed Apr 16 '15 at 13:34
2

that mechanism I told u about ...

if I have an Address entity

public class Address
{
    public int Id { get; set; }
    public string Street { get; set; }
    public string House { get; set; }
    public int Floor { get; set; }
}

and this is the controller actions AddressController

[HttpGet]
public ActionResult Index()
{
    var model = new SearchAddressesViewModel();

    // you can here also fetch all the addresses in your db ... 
    //but this is not a good approach also, but if you need to do that it's easy

    // fetch data base and get all addresses
    //model.AddressesFound = db.Addresses.Select(a => new AddressModel
    //{
    //    Street = a.Street,
    //    House = a.House,
    //    Floor = a.Floor
    //}).ToList();

    return View(model);
}

[HttpPost]
public ActionResult Index(SearchAddressesViewModel model)
{
    if (!ModelState.IsValid)
        return View(model);

    // fetch data base and get addresses based on the search criteria in 
    //model.SearchCriteria
    // for example:
    //var addresses = db.Addresses.Where(a => a.Street == model.SearchCriteria);

    //add found addresses to model

    //model.AddressesFound = addresses.Select(a => new AddressModel
    //{
    //    Street = a.Street,
    //    House = a.House,
    //    Floor = a.Floor
    //}).ToList();

    return View(model);
}

and here is my View Index.cshtml

@model SearchAddressesViewModel

@using (Html.BeginForm("Index", "Address", FormMethod.Post))
{
    @Html.LabelFor(m => m.SearchCriteria);
    @Html.TextBoxFor(x=>x.SearchCriteria);
    @Html.ValidationMessageFor(m => m.SearchCriteria, "");

    <br />
    <input type="submit" class="btn btn-block btn-success" value="Search" />
}

@if (Model.AddressesFound != null)
{
    <table>
        <thead>
            <tr>
                <th>Street</th>
                <th>House</th>
                <th>Floor</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var item in Model.AddressesFound)
            {
                <tr>
                    <td>@item.Street</td>
                    <td>@item.House</td>
                    <td>@item.Floor</td>
                </tr>
            }
        </tbody>
    </table>
}

and here it the view model I used SearchAddressesViewModel and AddressModel

public class SearchAddressesViewModel
{
    [Required]
    [Display(Name = "Search for address")]
    public string SearchCriteria { get; set; }

    public IList<AddressModel> AddressesFound { get; set; }
}

public class AddressModel
{
    public string Street { get; set; }
    public string House { get; set; }
    public int Floor { get; set; }
}

also you can use partial view for AddressModel in the view based on your case.

I hope that you got my point... thank you

Sherif Ahmed
  • 1,896
  • 1
  • 19
  • 37
  • Thanks Sherif for your help. Well yes that was a poor design solution from me. I should have used submitted the form to the Get Index method by having form's method as GET. Then in the Get Index method, I should have checked if the textbox value has been submitted or not, if it is then I use that address to fetch info from DB otherwise, just the default address. Since, @Sherif you pointed out that it is a bad approach, I will mark your answer as correct. Thanks! – Syed Apr 16 '15 at 13:53
  • @Syed Don't follow this advice, because it is very wrong. You have to redirect after a POST. Check the PRG pattern: https://en.wikipedia.org/wiki/Post/Redirect/Get. – L-Four Oct 12 '16 at 08:40
  • @L-Four ... please check this to be sure that this mechanism is the good for search filters [PRG Pattern with Search Filters on Action Method](https://stackoverflow.com/a/10628575/2907017) – Sherif Ahmed Aug 20 '17 at 11:34
  • Why would you use a post for search filter? It doesn't have any side effect, just querying data? – L-Four Aug 28 '17 at 13:22