Manage actions' and controllers' names in ASP.NET MVC - asp.net

I'm new in ASP.NET MVC,
I have many actions in my controllers, so they return different ActionResults like this:
return View("blablabla");
or
return RedirectToAction("actionName", "controllerName");
So what I don't like about this is amount of hard-coded string values of actions' and controllers' names. If I change the name of controller or action I have to go through all my code to change code everywhere, where this action/controller was returned as an ActionResult.
So, guys, how do you manage this situation? Do you extract all the names into classes with constant or static readonly string fields with names of actions/controllers?
Or maybe you use something else?

Check out MvcContrib - it has a helper extension method which adds type-safe redirects. In Microsoft.Web.Mvc.LinkExtensions, there's an ActionLink<TController> method which can take an expression. You use it like:
<%=Html.ActionLink<HomeController>(c=>c.About(), "Go To About") %>

Related

JsonResult or Json: which to use?

In ASP.NET MVC 3, which is more correct to use: Json() or new JsonResult()? Either returns the same result. Thanks for helping solve an office debate.
Json() is just an extension method that actually returns a JsonResult object behind the scenes (rather than needing to call the constructor directly).
I almost always use the Extension Method myself. This keeps more in line with the other common return types from Action Methods like View(), PartialView(), etc.
I also make sure to create an extension method for any custom ActionResult types that I create. In the end it's a matter of personal preference.
If you a returning a large dataset as a data source for grid or other UI controls via Ajax, sometimes if this dataset is over 1000 records UI controls will not bind because of maximum Json length is not specified.
So instead of
return Json(data),
you can do this: return new JsonResult(Data = data, MaxJsonLength = 50000);

Passing a list of object from a view to the controller in asp.net mvc?

Is this possible?
What I want to do is pass a list of objects as a paramter in an actionlink
At the moment when I try to do this the list is always empty by the time it reaches the controller!
In the view
<%= Url.Action("ActionName", new { list = Model.ListOfObjects}) %>
In the controller
public ActionResult ActionName(List<Object> list)
{
//Do stuff
}
In terms of whether or not it's possible - it's possible, but not in the way you're trying. Keep in mind that this will translate to a URL which will get parsed by MVC and the different parameters will get passed to the action either as direct parameters or through a model binder.
I would recommend that you try to figure out what the URL will have to look like and then maybe do some custom code to generate the URL (maybe use a custom helper function/extension method). If you combine this with a custom model binder you should have a pretty elegant solution which does exactly what you want.
For example, if your list has 3 objects of type string you could write a helper to generate a url like this (let's say the list contains 'first', 'second', and 'third')
/Controller/Action?obj1=first&obj2=second&obj3=third
Now you simply need to write a model binder that looks for entries called 'obj1','obj2', etc and simply add the results into a list.
While it may take the list of objects, it probably won't render what you are expecting to see; it may actually suck in the values of the list class (or whatever class this list represents) and use that as the params.
Not through a get request, unless you write out the params manually and deserialize the params too. Or, instead, do a postback to the server with these values within the form; then, this would populate correctly.
HTH.
Something like this would work, I suggest making a helper to contain this logic if you need it in a lot of places.
<% var values = new RouteValueDictionary();
for (int i = 0; i < Model.ListOfObjects.Count -1; i++)
{
values.Add("list["+i+"]", Model.ListOfObjects[i]);
}%>
<%= Url.Action("ActionName", values); %>
The action will know how to handle the list in the controller.

Removing null/empty keys from a query string in asp.net MVC

Is there a way I can remove null or empty keys from a query string in asp.net MVC? For example I have a page where I filter data on a results table, if I search for John the query string would be redisplayed as:
candidates?FirstName=John&LastName=&Credit=false&Previous=false&Education=&Progress=
and not
candidates?FirstName=John
I looked at URL routing but I wasn't sure if it was something that should be used for cosmetic things like this or if it is possible to achieve what I'm asking using it.
How are you generating that URL? With Routing, if those are meant to be in the query string, it should work fine. We only generate query string parameters for RouteValues that you specify.
One thing I've done in the past is to write my own helper method for specific links where I might pass in an object for route values, but want to clear out the values that I don't need before passing it to the underlying routing API. That worked well for me.
Whatever URL generator, or control you are using would need special logic to strip these unwanted tags from the list. It's not obvious to a generic URL generator or control that Credit=false is useless -- couldn't it be Credit=true is the default? Similarly an empty string can mean something. (Also, Lastname= is different from Lastname.
I sometimes need to work on my route values in partials that are used by variuos views.
Then I usualy access the routeDictionary and change it. The benefit you get is, that there is a good chance that the code will survive changes in the routing and that you can use routeValues in multiple generated URL.
Most people would argue that the best place for this code is not the view. But hopefully you get the idea.
The view code:
RouteValueDictionary routeValues = ViewContext.RouteData.Values;
routeValues.Remove(...);
routeValues.Add(...);
routeValues["Key"] = ...;
<%
using (Html.BeginForm(
Url.RequestContext.RouteData.GetRequiredString("Action"),
Url.RequestContext.RouteData.GetRequiredString("Controller"),
routeValues,
FormMethod.Get))
{ %>
Maybe use this Querystring Builder - iterate querystrings in the Request.QueryString dictionary and build a new one using the builder (or just string-concat them)?

Remove field in wsdl in Asp.net webservice

I'm generating dto classes with a template engine and would like to exclude some properties in an asmx webservice, what, if possible, is the best way to do this?
Ex:
[WebMethod]
public ProductPackages GetPackages()
{
ProductPackages packages = new ProductPackages();
packages.Packages.add(new PackageDTO());
return packages;
}
The PackageDTO contains some properties that's not relevant for this service.
But as the class can be regenerated any time i can't apply [XmlIgnore] to the fields.
So I'm looking for a way to apply a "exclude list" without touching the actual class.
Above is just an example, the template engine generates dto's for all tables in a given project, and I would like to be able to use them in services without needing to maintain a big bunch of nearly identical classes.
Just hit the same problem. You can exclude fields by marking them as internal.
public class Order
{
public double OrderPrice;
internal double ProfitMargin;
internal string TheTruthAboutThisCustomer;
}
If you don't want to return a field or property, then don't have it in the object you return! It's as simple as that.

How to create a simple ASP.NET MVC action method that accepts HTTP-POST data?

i wish to have a simple Action in my controller that accepts a few optional values and some integer values.
this is my route i wish to have:
HTTP.POST
/review/create
and this is the Action method i would like...
[AcceptVerbs(HttpVerbs.Post)]
public JsonResult Create(int userId,
int addressId,
byte baseScore,
byte reviewType,
string subject,
string description)
{ ... }
I'm under the uneducated impression that all of those arguments above will be populated by the forms collection values ... but it's not happening. Also, I have no idea how I would write a route, to handle those ... because those values are form post data....
here's my global.asax....
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// Api - Search methods.
routes.MapRoute(
"Search Methods",
"{controller}/{action}"
);
In fact, the action method is never called because it doesn't seem to find it :(
But, if create and action without any of those arguments, then it finds it ?????????
How would you write a route and action method to accept some require and some optional arguments, for the route /review/create ?
As far as i can see you may rewrite your controller action like this:
public ActionResult Create(int foo, int bar, byte blah, string name, int? xxx) {
// code here
}
The ModelBinder will then ensure that foo,bar and blah are set. Name and xxx may be null. I can't test it a the moment, but i think return type of the action should be ActionResult.
If you are POST'ing a form, just make sure that the elements in your form (textboxes, checkboxes, textarea, etc) have id's that match the parameters in your method. As an alternative you can pass a FormCollection to the method, and do myFormCollection["foo"] to get a string representation of the value (which can then be parsed to an int).
From my experience, you are missing a number of key elements and concepts with this question.
First and foremost, I don't believe you can execute a POST without a form. The form has to contain the controls from which you pull the values that get passed to the controller method. If the goal is to simply unit test your POST controller method, then just call the method directly in your test, which it appears that you're doing, based on one of your comments. If you involve the view, then you're doing integration testing, not unit testing. Regardless of the test type, the test will always fail because you are choosing not to build the form. Even if you manage to force the POST using Fiddler, Firebug or any other mechanism, you're still not testing the view, you're testing the HTTP protocol.
I highly recommend that you employ a web application testing tool, such as WatiN or Selenium, to test your web pages, rather than throw together a quick-and-dirty test that really doesn't test anything useful.
In your post request set content-type="application/json; charset=UTF-8" and pass the values for the method parameter in JSON format. This should make Asp.MVC not to look in FormCollection for those values.

Resources