views:

243

answers:

1

I want to use custom action filter to manipulate parameters to one action.

User inputs: 2 names in a form ;

Action: actually needs to take 2 ids;

Action Filter (onExecuting, will verify the input names and if valid, convert them into 2 ids and replace in the routedata)

because i don't want to put validation logic in Action Controller.

here's part of the code:

  1. Routing Info

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

    routes.MapRoute( "RelationshipResults", // Route Name "Relationship/{initPersonID}/{targetPersonID}", // URL with parameters new { controller = "Relationship", action = "Results" });

  2. Form to submit (Create 2 input box and submit via jquery)

    <% using (Html.BeginForm("Results", "Relationship", FormMethod.Post, new { id = "formSearch" })) {%>
    ...

        <td align="left"><%: MvcWeibookWeb.Properties.Resource.Home_InitPersonName%></td>
        <td align="right"> <%= Html.TextBox("initPersonID")%></td>
        <td rowspan="3" valign="top">
            <div id="sinaIntro">
            <%: MvcWeibookWeb.Properties.Resource.Home_SinaIntro %>
            <br />
            <%: MvcWeibookWeb.Properties.Resource.Genearl_PromotionSina %>
            </div>
        </td>
    </tr>
    <tr>
        <td align="left" width="90px"><%: MvcWeibookWeb.Properties.Resource.Home_TargetPersonName%></td>
        <td align="right"><%= Html.TextBox("targetPersonID")%></td>
    </tr>
    <tr>
        <td colspan="2" align="right">
            <a href="#" class="btn-HomeSearch" onclick="$('#formSearch').submit();"><%: MvcWeibookWeb.Properties.Resource.Home_Search%></a>
        </td>
    
  3. Action Filter

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        Sina.Searcher searcher = new Sina.Searcher(Sina.Processor.UserNetwork);
        String initPersonName, targetPersonName;
    
    
    
    // form submit names, we need to process them and convert them to IDs before it enters the real controller.
    initPersonName = filterContext.RouteData.Values["initPersonID"] as String;
    targetPersonName = filterContext.RouteData.Values["targetPersonID"] as String;
    
    // do sth to convert it to ids and replace
  4. Action/Controller

    [ValidationActionFilter] [HandleError] public ActionResult Results( Int64 initPersonID, Int64 targetPersonID) { ...

My problem is: in the actionFilter, it never gets the 2 parameters "initPersonID" and "targetPersonID", the RouteData.Values don't contain these 2 keys...

:(

A: 

The problem is that since your routes don't have any values for initPersonName and targetPersonName, they never end up in your route data. Try (even though it looks a little odd):

initPersonName = filterContext.RouteData.Values["initPersonID"] as String;
targetPersonName = filterContext.RouteData.Values["targetPersonID"] as String;

Since "...ID" whas what the values where called in your routes, that's what you have to look for in your route data. The fact that you're actually not including the ID's in the url is another matter...

Tomas Lycken
thanks Toms, it doesn't worki've changed them (updated inline)
Goden
let me correct 1 thing, if i type http://localhost/relationship/name1/name2it does trigger the action filter and get my values, but if i submit through the form, i don't get them.
Goden
Now things are getting interesting, i can get the form data by filterContext.HttpContext.Request.Form["initPersonID"] if data submitted from form. but i can use initPersonName = filterContext.RouteData.Values["initPersonID"] as String; to get the string if directly typing the name in URL. so why these 2 are not united?
Goden
@Goden: When you submit values form a form, you don't get them as route data at all. Google for ASP.NET MVC Model Binders, and you'll find what to do.
Tomas Lycken
@Goden: you could unite them yourself if you want - there are Linq extensions for IEnumerable<T> for that. =)
Tomas Lycken
but i do get them from routedata if there's no actionFilter.
Goden