Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8434029
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 10, 20262026-06-10T06:32:50+00:00 2026-06-10T06:32:50+00:00

Maybe I’m thinking about this the wrong way, coming from a recent delve into

  • 0

Maybe I’m thinking about this the wrong way, coming from a recent delve into WPF and MVVM, but I have the following ViewModels in my Web project.

public class Route
{
    public Address Source {get; set;}
    public Address Destination {get; set;}
}

public class Address
{
    public string Text {get; set;}
    public Location Location {get; set;}
}

puclic class Location
{
    [Required]
    public double? Latitude {get; set;}
    [Required]
    public double? Longitude {get; set;}
}

public class Search
{
    public Route {get; set;}
    public IEnumerable<Route> Results {get; set;}
}

I have the following views (_ prefixed views are partial)

   Home.cshtml - the main page, has @model Search with call to @Html.Partial("_Route", Model.Search) inside an Ajax.BeginForm.

   _Route.cshtml - @model Route, with two Html.Partials for _Address, one for Model.Source and one for Model.Destination

   _Address.cshtml - @model.Address, with a text box which should be "bound" to the Address.Text property.

In case it’s not clear what I’m trying to do – I’m trying to get the user to enter some search text in a source box and a destination box and then get results. The Source and Destination boxes should AutoComplete via Ajax and populate Address.Location.Latitude and Address.Location.Longitude when the user picks one of the AutoComplete choices.

Finally, once the user has valid Source and Destination Locations, the Submit button on the Home.cshtml should call via Ajax to get the search results and bind them to a grid.

Pretty standard stuff I guess…

I’m struggling with the “cleanest” way to accomplish the following:

  1. Since Location isn’t actually displayed anywhere in the Address view (just Text), how can I get ASP.NET MVC’s DataAnnotations validation to kick in and help me validate?

  2. When the user picks one of the AutoComplete choices, how do I get the Location values to bubble back up to the Home.cshtml which should POST a Route object via an Ajax call?

  3. How should I maintain the “state” of the user’s selected Addresses in the Source and Destination? Add a Select handler to the AutoComplete? But then do what with the selected value?

I hope this is clear…but if not, let me know and I’ll try to clarify.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-10T06:32:51+00:00Added an answer on June 10, 2026 at 6:32 am

    You could use jQuery UI autocomplete. Let’s take an example.

    We could have the following models:

    public class Route
    {
        public Address Source { get; set; }
        public Address Destination { get; set; }
    }
    
    public class Address
    {
        [Required]
        [ValidCity("Location", ErrorMessage = "Please select a valid city")]
        public string Text { get; set; }
        public Location Location { get; set; }
    }
    
    public class Location
    {
        public double? Latitude { get; set; }
        public double? Longitude { get; set; }
    }
    
    public class Search
    {
        public Route RouteSearch { get; set; }
        public IEnumerable<Route> Results { get; set; }
    }
    

    And here’s the [ValidCity] custom validator that we used on the Address class:

    public class ValidCityAttribute : ValidationAttribute
    {
        private readonly string _locationPropertyName;
        public ValidCityAttribute(string locationPropertyName)
        {
            _locationPropertyName = locationPropertyName;
        }
    
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var property = validationContext.ObjectType.GetProperty(_locationPropertyName);
            if (property == null)
            {
                return new ValidationResult(string.Format("Unknown property: {0}", _locationPropertyName));
            }
            var location = (Location)property.GetValue(validationContext.ObjectInstance, null);
            var city = value as string;
    
            if (!string.IsNullOrEmpty(city) && location != null && location.Latitude.HasValue && location.Longitude.HasValue)
            {
                // TODO: at this stage we have a city name with corresponding 
                // latitude, longitude => we could validate if they match
                // right now we suppose they are valid
    
                return null;
            }
    
            return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
        }
    }
    

    Then a controller:

    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            var model = new Search
            {
                RouteSearch = new Route
                {
                    Source = new Address(),
                    Destination = new Address()
                }
            };
            return View(model);
        }
    
        [HttpPost]
        public ActionResult Index(Route search)
        {
            if (!ModelState.IsValid)
            {
                return PartialView("_Route", search);
            }
    
            // TODO: do the search here and return the results:
    
            var lat1 = Math.PI * search.Source.Location.Latitude.Value / 180;
            var lon1 = Math.PI * search.Source.Location.Longitude.Value / 180;
    
            var lat2 = Math.PI * search.Destination.Location.Latitude.Value / 180;
            var lon2 = Math.PI * search.Destination.Location.Longitude.Value / 180;
    
            var R = 6371;
            var distance = Math.Acos(Math.Sin(lat1) * Math.Sin(lat2) +
                              Math.Cos(lat1) * Math.Cos(lat2) *
                              Math.Cos(lon2 - lon1)) * R;
            return Json(new { distance = distance });
        }
    
        public ActionResult GetLocation(string text)
        {
            var results = new[]
            {
                new { city = "Paris", latitude = 48.8567, longitude = 2.3508 },
                new { city = "London", latitude = 51.507222, longitude = -0.1275 },
                new { city = "Madrid", latitude = 40.4, longitude = -3.683333 },
                new { city = "Berlin", latitude = 52.500556, longitude = 13.398889 },
            }.Where(x => x.city.IndexOf(text, StringComparison.OrdinalIgnoreCase) > -1);
    
            return Json(results, JsonRequestBehavior.AllowGet);
        }
    }
    

    a corresponding ~/Views/Home/Index.cshtml view:

    @model Search
    
    @using (Ajax.BeginForm(new AjaxOptions { OnSuccess = "searchComplete" }))
    {
        <div id="search">
            @Html.Partial("_Route", Model.RouteSearch)
        </div>
        <p><button type="submit">OK</button></p>
    }
    

    The ~/Views/Home/_Route.cshtml partial:

    @model ToDD.Controllers.Route
    
    <h3>Source</h3>
    @Html.EditorFor(x => x.Source)
    
    <h3>Destination</h3>
    @Html.EditorFor(x => x.Destination)
    

    and the editor template for the Address class (~/Views/Home/EditorTemplates/Address.cshtml):

    @model Address
    
    <span class="address">
        @Html.TextBoxFor(x => x.Text, new { data_url = Url.Action("GetLocation") })
        @Html.ValidationMessageFor(x => x.Text)
        @Html.HiddenFor(x => x.Location.Latitude, new { @class = "lat" })
        @Html.HiddenFor(x => x.Location.Longitude, new { @class = "lon" })
    </span>
    

    The last part is to make everything alive. We start by including the following scripts (adjust the versions of jQuery and jQuery UI that you are using):

    <script src="@Url.Content("~/Scripts/jquery-1.7.1.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery-ui-1.8.20.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
    

    and finally we write our custom script to wire everything up:

    var searchComplete = function (result) {
        if (result.distance) {
            alert('the distance is ' + result.distance);
        } else {
            $('#search').html(result);
            attachAutoComplete();
        }
    };
    
    var attachAutoComplete = function () {
        $('.address :text').autocomplete({
            source: function (request, response) {
                $.ajax({
                    url: $(this.element).data('url'),
                    type: 'GET',
                    cache: false,
                    data: { text: request.term },
                    context: response,
                    success: function (result) {
                        this($.map(result, function (item) {
                            return {
                                label: item.city,
                                value: item.city,
                                latitude: item.latitude,
                                longitude: item.longitude
                            };
                        }));
                    }
                });
            },
            select: function (event, ui) {
                var address = $(this).closest('.address');
                address.find('.lat').val(ui.item.latitude);
                address.find('.lon').val(ui.item.longitude);
            },
            minLength: 2
        }).change(function () {
            var address = $(this).closest('.address');
            address.find('.lat').val('');
            address.find('.lon').val('');
        });
    }
    
    $(document).ready(attachAutoComplete);
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Maybe the need to do this is a 'design smell' but thinking about another
Maybe I'm just thinking about this too hard, but I'm having a problem figuring
Maybe it's wrong but I always use this query for my app: cme_only =
Maybe this is something I am just missing, but is there any way to
Maybe I am trying to approach this the wrong way... In my main view
Maybe this is a dumb question, but is there any way to convert a
Maybe it's because of the dark outside, but I can't get this Position geom_text
Maybe this is a poor question, but, I can't find a tutorial or even
Maybe this is a simple question, but I didn't find answer in web. I
Maybe this is a no-brainer but i cant see the solution right now :)

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.