Help adding a route

Topics: Writing modules
Jun 5, 2011 at 8:24 AM

Okay, Granted i'm very new to MVC 3, it's not deterring me from using this as a great platform to learn from.

I'm working on Adding some functionality to a new module.. and eventually transform it into a Widget.

I have a home controller, and ofcourse I have my main ActionResult, and an additional Action Result later on in the code:

    public class HomeController : Controller {
        public ActionResult Index() {
            return View("x7Chat");
        }
    }

        [HttpPost]
        public ActionResult New(string user, string msg)
        {
            ChatServer.AddMessage(user, msg);
            return Json(new
            {
                d = 1
            });
(yes, i'm building an MVC Chatserver based on an example I found by Jacob Gable of Claritycon.com - Roll your own MVC3 long polling chat site)

So, the Route that I have requires me to post things to x7Chat/New, where it should be picked up by the HomeController and added to my Messaging Model, 
which is what the 'New' Action result does.
The problem I'm having, is that I can't figure out how to make it Route correctly.  Currently it looks like this:
        public IEnumerable<RouteDescriptor> GetRoutes()
        {
            return new[] {
                new RouteDescriptor {
                    Priority = 5,
                    Route = new Route(
                        "x7Chat",
                        new RouteValueDictionary {
                            {"area", "x7Chat"},
                            {"controller", "Home"},
                            {"action", "Index"}
                        },
                        new RouteValueDictionary(),
                        new RouteValueDictionary {
                            {"area", "x7Chat"}
                        },
                        new MvcRouteHandler())
                },
                new RouteDescriptor {
                    Priority = 5,
                    Route = new Route(
                        "x7Chat/New",
                        new RouteValueDictionary {
                            {"area", "x7Chat"},
                            {"controller", "Home"},
                            {"action", "New"}
                        },
                        new RouteValueDictionary(),
                        new RouteValueDictionary {
                            {"area", "x7Chat"}
                        },
                        new MvcRouteHandler())
                }

            };

        }
    }
}
Can anyone give me a hint, or the answer i'm looking for?  I can't get it to process/route thru correctly.
Much thanks!
Jun 5, 2011 at 7:43 PM

- What URL are you trying to access?

- What error do you see there?

- What's the full name of your module? Is it "x7Chat" or is it "SomeNamespace.x7Chat"?

Jun 5, 2011 at 8:21 PM

well, for now, it's just http://orchardlocal:30020/x7Chat/New  since i'm in the dev environment. 

The module name is simply x7Chat

Lastly, I'm not getting an error, i'm just not able to to get messages that are posted to x7Chat/New to process thru the "New" Action HomeController Code.  I'm going to assume that it's a routing thing.

Jun 5, 2011 at 8:50 PM
Edited Jun 5, 2011 at 8:50 PM

You need the controller name in the URL - so it should be /x7Chat/Home/New . The reason I mentioned the module name is because the area name should be the same as your full module name; as long as your module is called x7Chat that's fine; but normally I include a namespace as well because it makes it easier if you make more modules.

Jun 5, 2011 at 9:00 PM

Thanks, Will give that a try.

Jun 5, 2011 at 9:24 PM

http://localhost:30320/OrchardLocal/x7Chat/Home/New/   Doesn't work.. I still think I need to do something with the second Route.. Should I change it to something like:

                new RouteDescriptor {
                    Priority = 5,
                    Route = new Route(
                        "x7Chat/Home",
                        new RouteValueDictionary {
                            {"area", "x7Chat"},
                            {"controller", "Home"},
                            {"action", "New"}
                        },
                        new RouteValueDictionary(),
                        new RouteValueDictionary {
                            {"area", "x7Chat"}
                        },
                        new MvcRouteHandler())

Yields: 

 Server Error in '/OrchardLocal' Application. Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.

Requested URL: /OrchardLocal/x7Chat/Home/New/


The resource cannot be found.

 

 

Jun 5, 2011 at 11:12 PM
Edited Jun 5, 2011 at 11:13 PM

Ok I missed that you were explicitly specifying the URL. So yes it should be /x7Chat/Home.

So; now you can see the error you get when a URL is wrong. So the fact you didn't get an error before means that your route was right, but the controller's doing something wrong.

I take it you are POSTing to the New action, not GETting?

Do you see the JSON result that you returned?

Without seeing the rest of your code, i.e. ChatServer, I don't know what else could be going wrong.

Jun 6, 2011 at 3:56 AM
Edited Jun 6, 2011 at 4:05 AM

Kinda hard to show all the code here.. But let me explain it a different way...
If I send a command to x7Chat/New(usr, msg), I should be able to trap it in the
HomeController the same way I trap Index() when I try to reference it from a URL. 

Really tho, If you take everything away from the code, other than the fact that I
need to figure out how to correctly setup the route in Routes.cs so, when I send
something to x7Chat/Home/New or x7Chat/New, that the javascript code I'm
using to send and recieve messages from x7Chat/Home/New or just regular
x7Chat/New  or whatever I can use.. is totally irrelevant.  The fact remains, I can't
get trap the action on /New because the resource cannot be found. 

I appreciate your help trying to help me thru this. 

~D

~~Edit~~
When I look at the original code from the example Its route shows:

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

So, If I changed my Route.cs file to reflect this...

                        new RouteValueDictionary {
                            {"area", "x7Chat"},
                            {"controller", "Home"},
                            {"action", "Index"},
                            {"id", ""}
                        },

I should be able to refrerence the New() controller class by sending info to x7Chat/Home/New that way.. or x7Chat/Home/Index/New
Does that sound right?

Jun 6, 2011 at 4:38 AM
Edited Jun 6, 2011 at 4:38 AM

Your original post had the correct routing for /x7Chat/New. You said "I'm not getting an error ". Was this correct, or were you seeing "Resource cannot be found" even with that original routing? That's still an error you know.

The thing is, you've specified [HttpPost] for that action - so it requires a POST; trying to access that URL normally (by entering it in your browser, which is a GET) won't work because you haven't defined a GET route.


Jun 6, 2011 at 5:28 AM
Edited Jun 6, 2011 at 5:44 AM

After looking at the code by putting in the full URL, it is coming back with an error.  When I was trying to run it thru the code, It wouldn't error out.

both /OrchardLocal/x7Chat/Home/New/ and /OrchardLocal/x7Chat/New/   error out.

It was working tho when i was playing with optional url params tho..

Jun 6, 2011 at 11:50 AM

Do you get what I have said a couple of times already: that route will only respond to HTTP POST, because that's what you specified on the action.

Jun 10, 2011 at 6:57 AM

Pete.. Most of what you said has sunk in.. Thanks.  As I said, I'm new to MVC, and Orchard is a bit different.  But, I now have the routes routing, the models working right.. 
What I ended up doing was removing the HTTPPost and testing the route via the address bar, trapping it as it processed, and then marking it as a successfull route. 

So, we can close here.

The actual problem that I'm having now is related to how you submit a form, via javascript.  Once I figure that part out, I think i'll be good.  But for that, I'll search
Thru the discussions first, and then drop a message if I get stuck.

~Dan

Jun 10, 2011 at 7:00 AM

With JQuery you could $("form").submit();

Don't forget to specify the form method="post" if you've set an HttpPost on the action.

Jun 10, 2011 at 7:30 AM

Sharp, thanks for the reply.

I was looking at the JQuery site.. and they specifiy this as the way to post:

$.post('x7Chat/New', { name: "John", msg: "I like potatos" });

Which is the style i'm using.. For Orchard tho, Should I Create a form variable and go at it this way?

var
$form = $(#msgBtn).parents('form');

$.ajax({           
type: "POST",           
url: $form.attr('x7Chat/New'),           
data: {name:"John", msg:"I like potatos"}
});

Which would mean i'd have to put form tags around my msgbox and submit button... right?

Jun 10, 2011 at 8:06 AM

You can do the post with ajax. But you can also use the actual submit method of the html form element.

It depends on what your aim is. If it's just submiting values, why not use the <input type="submit" value="Submit"/> and let the browser take care of it. Should you need some special checking before submiting I would do it like this

$("#button-id").click(function(){
// perform whatever you need
$(".form-class-name").submit();
}

Also consider using Html.RouteUrl, instead the url in the javascript function. Html.BeginFormAntiForgery should construct the post url correctly, which is why I usually just select the form and post the values.

So if you care to just send data and not redirect to another page, you can use the $.post( @Html.RouteUrl( route_name, ...), and send the data by calling $(".form-class-name").serialize. Have a look at here http://api.jquery.com/serialize/