ArmanKond
ArmanKond

Reputation: 11

Asp.net mvc routing using string params instead of Id on CRUD actions

I need to get urls with string name and able to edit/update it.

public class Person
{
    public int Id {get; set;}
    public string Name { get; set; }
    public string LastName { get; set; }
    public string City { get; set; }
}

Controller

  public ActionResult Edit(int id)
    {
        var person = _personService.Find(id);
        PersonViewModel model = Mapper.Map<Person, PersonViewModel>(person);
        return PartialView("_Edit", model);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit(PersonViewModel model)
    {
        if (ModelState.IsValid)
        {
            var person = _personService.Find(model.Id);

            person.Id = model.Id;
            person.Name = model.Name;
            person.LastName = model.LastName;
            person.City = model.City;

            _personService.Update(person);
            _uow.SaveChanges();
            return RedirectToAction("Index");
        }

        return PartialView("_Edit", model);
    }

View

    <div id="myModal" class="modal fade in">
        <div class="modal-dialog">
        <div class="modal-content">
            <div id="myModalContent"></div>
        </div>
    </div>
</div>
<div class="pull-right">@Html.ActionLink(" ", "Add", "Person", null, new { data_modal = "", id = "btnCreate", @class = "btn btn-md glyphicon glyphicon-plus" })</div>


@foreach(var person in Model)
{

    <p>@person.Name</p>
    <p>@person.LastName</p>
    <p>@person.City</p>
    @Html.ActionLink(" ", "Edit", "Person", new { id = person.Id}, new { data_modal = "", @class = "btn btn-danger btn-sm glyphicon glyphicon-edit" })

}

When I use like this there is no problem. And url is localhost/Person/Edit/1.

I want to get url like localhost/Person/Edit/John. And for details view the url must be localhost/Person/John instead of Person/Deatils/John.

In domain model I remove Id column then make the Name column primary [Key]. Using FindByName(name) in my repository, Edit(string name) in action and context.MapRoute( "Person", "Person/{action}/{name}", new { controller = "Person", action = "Index"} ); in route config I can achive this. But I can not edit Name column because it is primary key. I need name editable. So can i use the Id column as key so i can edit/update the name with no problem like in my first case but using urls like Edit/John with no id in it?

Upvotes: 0

Views: 1728

Answers (1)

SimonGates
SimonGates

Reputation: 6121

You will need some form of unique value in the URL. Imagine if you have more than one john?

If you don't mind having a URL like /Person/Edit/1/John

Then, for your given scenario (untested)..

public class Person
{
    [Key]
    public int Id {get; set;}
    public string Name { get; set; }
    public string LastName { get; set; }
    public string City { get; set; }
}

Add a route:

context.MapRoute( "Person", "Person/{action}/{id}/{name}", new { controller = "Person", action = "Index", id = UrlParameter.Optional, name = UrlParameter.Optional} ); 

Action:

public ActionResult Edit(int id, string name)
{
    var person = _personService.Find(id);

    // Optional, but you may want to ensure the Url is correct. of if name is
   // missing add it.
    if(string.IsNullOrEmpty(name) || (person.Name.ToUrlFriendly() != name.ToUrlFriendly()))
    {
        return RedirectToRoute(..... new {id = person.Id, name = person.Name.ToUrlFirendly() });
    }

    PersonViewModel model = Mapper.Map<Person, PersonViewModel>(person);
    return PartialView("_Edit", model);
}

Note the ToUrlFriendly() this is to ensure the URL is a valid one, and will generate urls-like-this-one and remove invalid chars. See here for more details and implementation.

https://stackoverflow.com/a/25486/387809

Upvotes: 0

Related Questions