Best asp.net-mvc-3 questions in February 2012

Where can I find Upshot.js examples and documentation?

13 votes

Steve Sanderson gave a very interesting presentations at Techdays 2012 in the Netherlands. In one of them he presented a library that he used for client-server communication in MVC application: Upshot.

I was really amazed how easy it was to use it, so I wanted to download and test it. I found the download link here through NuGet, but I cannot find any documentation. Does anyone have something that works? I would also appreciate the sample code that Steve showed as during presentation.

EDIT:

I found the online presentation I attended at Techdays. It's soooo much worth seeing. You will get a glance of what upshot is capable of and also get an idea how to start with it. Good luck and have fun.

The link: http://channel9.msdn.com/Events/TechDays/Techdays-2012-the-Netherlands/2159

I found one which is one of the MS samples for SPAs (which might be the only one for now):

ASP.NET Single Page Application (SPA) BigShelf

The complete tutorial on this project can be found here: BigShelf

Edit:

See this tweet from Steve Sanderson: https://twitter.com/#!/stevensanderson/status/171561402597773312

We're setting up a website for Upshot/SPA right now. Hopefully will go live this week! Sorry for delay.

AntiForgeryToken invalid after sign in

7 votes

I have a form which the user can post without loging in. If however his email is recognized a password is required. The password form is validated over Ajax and if successfull the main form is submitted. Both forms require a valid AntiForgeryToken.

The catch is, the password check as a biproduct also signs the user in (a requirement from the client). This invalidates the token and the main form cannot be sent.

I have tried programmatically generating a new token but I can't get it to work.

Any ideas on how to resolve this?

Final solution

I found this question to be helpful in type up the reflection. However, and this is the main reason why under normal circumstances you would avoid hacking internal types, is that the types are juggled between assemblies alot between releases. As Betty suggests, use ILSpy to find things.

This is the final code.

if (signIn)
    FormsAuth.SignIn(user.Email, false);


var mvcAssembly = typeof(AntiForgery).Assembly;
var afdType = mvcAssembly.GetType("System.Web.Helpers.AntiForgeryData");
string fieldName = Convert.ToString(afdType.InvokeMember(
    "GetAntiForgeryTokenName",
    BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.InvokeMethod,
    null,
    null,
    new object[] { null }));

var serializerType = mvcAssembly.GetType("System.Web.Helpers.AntiForgeryDataSerializer");
var serializerCtor = serializerType.GetConstructor(new Type[0]);
object serializer = serializerCtor.Invoke(new object[0]);


string text = HttpContext.Request.Form[fieldName];
object antiForgeryData = serializerType.InvokeMember("Deserialize", BindingFlags.InvokeMethod, null, serializer, new object[] { text });

afdType.GetProperty("Username").SetValue(antiForgeryData, 
    signIn ? user.Email : string.Empty, 
    null);

string newToken = Convert.ToString(serializerType.InvokeMember(
    "Serialize",
    BindingFlags.InvokeMethod,
    null,
    serializer,
    new object[] { antiForgeryData }));

return Content(JsonConvert.SerializeObject(new
                                                {
                                                    success = true,
                                                    newAntiForgeryToken = newToken
                                                }), Constant.JsonContentType);

The current user is stored in the anti-forgery token in the form data and compared with the current user on postback.

You should be able to pull out the form token on postback in the same way Phil Haack does it in this post (http://haacked.com/archive/2011/10/10/preventing-csrf-with-ajax.aspx).

Then use the AntiForgeryDataSerializer class to deserialize the token, update the current user, serialize it again and put it back in the form before it's checked. Or replace the validate method entirely using your own attribute.

Alternatively, instead of updating it on the main forms postback, you could try send the updated token back with the password ajax request and update the form. Either way the basic approach is the same, deserialize, update user, serialize, replace token.

string antiForgeryTokenName = AntiForgeryData.GetAntiForgeryTokenName(null);
string text = context.Request.Form[antiForgeryTokenName];
AntiForgeryDataSerializer serializer = new AntiForgeryDataSerializer();

AntiForgeryData antiForgeryData = serializer.Deserialize(text); 
antiForgeryData.Username = AntiForgeryData.GetUsername(context.User);
string newToken = serializer.Serialize(antiForgeryData);    

AntiForgeryDataSerializer and AntiForgeryData are internal classes, so you will have to use some basic reflection to call methods on them.

Is there a .NET equivalent to Rails Console?

6 votes

Rails Console is so useful for direct sanity-checking of your model. Is there an ASP.NET MVC equivalent?

Is it possible to mimic Rails Console behaviour using LinqPAD?

awesome - I discovered LinqPAD 4.38.03 (latest beta version) works perfectly well as a Rails Console substitute!

My ASP.NET MVC3 project is based on Entity Framework 4.2 (using the "database first" approach) which Linqpad integrates nicely with. I am able to reference my assembly as a connection and query the model, controller, repositories etc. interactively, just like in Rails Console!

These were my steps

  1. In the Connection manager (to the left) click "Add connection"
  2. click the radio labelled "use a typed data context from your own assembly"
  3. click "Entity Framework dbContext POCO (4.1/4.2)", then "next"
  4. use "browse" to locate the "path to custom assembly" (in your project)
  5. click "choose" to select the dbContext class from your assembly
  6. click "choose" to locate your project config file in "path to application config file"
  7. type an optional connection name, click "next"

Finally, in your query window select your new assembly connection as the "Database" and that's it! You can now work with your assembly interactively.

For example, to inspect and test a controller: (first, in Query Properties, add a reference to System.Web.Mvc)

var controller = MyProject.Controllers.CustomerController();
controller.Index().Dump();

to "post" some data

var customer = new Customer() {name = "Brian"};
controller.Create(customer);

to see your new Customer in the database

Customers.Dump();

or if you have a repository

var repo = new Repository();
repo.GetCustomers().Dump();

Custom authorization in ASP.NET MVC 3

5 votes

I am migrating an application from ASP.NET Web Forms to ASP.NET MVC 3. One of the central and critical pieces is currently locked away in its own directory. I have restricted unauthorized user from accessing this directory by using the following in my web.config file:

<location path="home" allowOverride="false">
  <system.web>
    <authorization>
      <deny users="?"/>
      <allow users="*"/>
    </authorization>
  </system.web>
</location>

My question is, how do I implement this same type of security in ASP.NET MVC 3? I have a hunch that it involves setting attributes on my Controller classes. However, the AuthorizeAttribute looks like it only accepts a list of user names and not an auth status (please correct me if I'm wrong). I looked at the sample ASP.NET internet application and I didn't see anything special being configured in it.

Can someone please point me in the correct direction on this?

Thanks!

That's correct, you'll utilize the AuthorizeAttribute, like so:

 [Authorize]
 public ActionResult AuthenticatedUsers()
 {
     return View();
 }

 [Authorize(Roles = "Role1, Role2")]
 public ActionResult SomeRoles()
 {
     return View();
 }

 [Authorize(Users = "User1, User2")]
 public ActionResult SomeUsers()
 {
     return View();
 }

As for "auth status", I'm not sure I know what you mean. It sounds like Roles would handle that authentication requirement.

How to Trim() all inputs by Model in c# MVC

5 votes

I found all value passed by Model is not trimmed in ASP.net MVC3

Is there a way to:

  1. Apply a trim() on every field in Model (all string fields, at least; but all form fields are string before processed by Model, so better trim them all)
  2. Must before ModelState.IsValid() (because I often found code stucked at weird ModelState.IsValid and later found because the form item did not be trimmed.)

Thanks.

You'll have to create a custom model binder to trim any model property that is a string.

References:
Custom model binding using IModelBinder in ASP.NET MVC
Iterating on an ASP.NET MVC Model Binder
6 Tips for ASP.NET MVC Model Binding
A Better Model Binder

Basically, you can take one of two approaches:

  1. Implement the IModelBinder interface
  2. Subclass the DefaultModelBinder class

Example

public class StringTrimmingBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // trim your string here and act accordingly

        // in the case the model property isn't a string
        return base.BindModel(controllerContext, bindingContext);
    }
}