Как передать специальные символы, чтобы ASP.NET MVC мог корректно обрабатывать строковые данные запроса?

Я использую маршрут, подобный этому:

routes.MapRoute("Invoice-New-NewCustomer",
    "Invoice/New/Customer/New/{*name}",
    new { controller = "Customer", action = "NewInvoice" },
    new { name = @"[^\.]*" });

Есть действие, которое обрабатывает этот маршрут:

public ActionResult NewInvoice(string name)
{
    AddClientSideValidation();
    CustomerViewData viewData = GetNewViewData();
    viewData.InvoiceId = "0";
    viewData.Customer.Name = name;
    return View("New", viewData);
}

Когда я вызываю return RedirectToAction("NewInvoice", "Customer", new {name});, а имя равно "С# Guy", параметр "name" усекается до "The C".

Итак, мой вопрос: какой лучший способ обработать этот особый символ с помощью ASP.NET MVC?

Спасибо!

Ответы

Ответ 1

Хорошо, я подтвердил, что это уже известная проблема в ASP.NET Routing, к сожалению. Проблема в том, что в глубине неровностей маршрутизации мы используем Uri.EscapeString при выходе из параметров маршрутизации для Uri. Однако этот метод не пропускает символ "#".

Обратите внимание, что символ # (aka Octothorpe) является технически неправильным символом. C♯ язык на самом деле является "C", за которым следует знак Sharp, как в музыке: http://en.wikipedia.org/wiki/Sharp_(music)

Если вы использовали резкий знак, который потенциально может решить эту проблему.: P

Другое решение, так как большинство людей захотят использовать octothorpe, это написать собственный маршрут для этого маршрута и после получения пути виртуального пути закодировать знак #, используя HttpUtility.UrlEncode, который кодирует # до% 23.

В качестве продолжения я хотел указать вам на это сообщение в блоге, в котором говорится о передаче других "недопустимых" символов. http://haacked.com/archive/2010/04/29/allowing-reserved-filenames-in-URLs.aspx

Ответ 2

Кодирование URL! Измените ссылку так, чтобы она кодировала специальные символы.

Server.URLencode(strURL)

С# станет "c% 23".

Ответ 3

Работает на моей машине. Вот что я сделал, чтобы создать простейший возможный пример.

//Global.asax.cs

using System.Web.Mvc;
using System.Web.Routing;

namespace MvcApplication4 {
  public class MvcApplication : System.Web.HttpApplication {
    public static void RegisterRoutes(RouteCollection routes) {
      routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

      routes.MapRoute(
        "Default",                        // Route name
        "{controller}/{action}/{id}",               // URL with parameters
        new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
      );

      routes.MapRoute("Invoice-New-NewCustomer",
            "Invoice/New/Customer/New/{*name}",
            new { controller = "Customer", action = "NewInvoice" },
            new { name = @"[^\.]*" });
    }

    protected void Application_Start() {
      RegisterRoutes(RouteTable.Routes);
    }
  }
}

//HomeController.cs
using System.Web.Mvc;

namespace MvcApplication4.Controllers {
  [HandleError]
  public class HomeController : Controller {
    public ActionResult Index() {
      return RedirectToAction("NewInvoice", "Customer", new { name = "The C# Guy" });
    }
  }
}

//CustomerController.cs
using System.Web.Mvc;

namespace MvcApplication4.Controllers {
    public class CustomerController : Controller {
        public string NewInvoice(string name) {
            return name;
        }
    }
}

Затем я начал свое приложение и перешел в /home/index. Переадресация происходит, и я видел "С# Guy" в моем браузере.