utorak, 2. srpnja 2013.

ASP.NET MVC4 Facebook app GetCurrentUserAsync problem with custom fields and how to locate an error

OK - my next problem: I tried to add some additional fields into a class with whom I model friends of my app user. I assumed, additional fields will be automatically ignored (either by facebook or by api) - they weren't. Suppose we have a class:

public class FbFriend
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string Link { get; set; }

    public User AppUser { get; set; }
}

The field "AppUser" will be initialized right after the request if my FbFriend is an user in my application. However, I was constantly getting an error. Even worse - I couldn't see wher the exception occured. For instance, I had this code:

var task = ctx.Client.GetCurrentUserAsync<FbUser>();
task.Wait();

var user = task.Result;

And all that I could see is that my user object had all nulls for fields. First step is seeing how to locate an error - assuming one develops with Visual Studio 2012, here is the screenshot:

Using mouse over on your context object, navigate to http request:


Copy paste entire URL into browser and read the result:


In my case, field AppUser is unknown. The last step is to tell the Facebook.Mvc to ignore field AppUser. It does not work with IgnoreDataMember, nor it works with NonSerialized attribute, but works only with JsonIgnore:
public class FbFriend
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string Link { get; set; }

    [JsonIgnore]
    public User AppUser { get; set; }
}
Problem: [solved].

srijeda, 26. lipnja 2013.

ASP.NET MVC4 Facebook application, facebook authorization and form post data

OK - so I've seen this great tutiral on creating Facebook app's with ASP.NET MVC4. I figured - this will be peace of cake - I have a cool idea which I'm about to implement, and just follow this steps and everything should work. However, this is never true. First thing I stumbled upon were simple post-forms. The problem is when one uses FacebookAuthorize attribute on an action or a controller, and attempts a simple post to this page, it simply doesn't work! The problem is further described in this stackoverflow question

Basically, the problem is because for some reason FacebookAuthorize filter makes a redirect to check the identity of an user. It took me at least 2 hours to find a reason for this behaviour - the code is actually available online to see, on this github link. The solution lies in code between lines 50 and 60 - FacebookAuthorize checks if there exists a specific request parameter, named "signed_request", and if it does not exist, the redirect is made and all our post data is lost.

The best solution I could come up is making a simple hidden field inside our form which is named "signed_request" and contains this request. For that purpose, I've made this nice extender method that does the job:


public static class FacebookHelpers
    {
        public static MvcHtmlString RenderAuthorizationToken(this HtmlHelper helper)
        {
            var signedReqValue = helper.ViewContext.RequestContext.HttpContext.Request["signed_request"];

            TagBuilder hdnBilder = new TagBuilder("input");
            hdnBilder.Attributes.Add("type", "hidden");
            hdnBilder.Attributes.Add("name", "signed_request");
            hdnBilder.Attributes.Add("value", signedReqValue);

            return MvcHtmlString.Create(hdnBilder.ToString(TagRenderMode.SelfClosing));
        }
    }
It can be used like this using razor: @Html.RenderAuthorizationToken()
Problem: [solved].

subota, 1. lipnja 2013.

Moving SQL server database files

Lately my VPS server C disk space seems to be filling-up rapidly. So I decided to get some extra space (its risky to append C-disk space, so I agreed to create additional partition) - let's call it E. Since my database .mdf files seem to take too much space, let's try to move them to this new partition.

First, I tried to detach the database, copy it to new location, and try to reattach it. Unfortunately - it doesn't seem to work. Exception was:

Unable to open physical file - Operating system error 5: 5(error not found) Microsoft SQL Server: Error 5120

After few minutes of google-ing, problem appeared to be due to security restrictions. Easiest way (allthough not the most secure) is to share a folder that my .mdf copy is located - unfortunately, it didn't work either - again the same exception.

After a bit more google-ing, found some solutions saying to allow sql express service full control over that specific file. That sounded like a splendid idea, but as a no-system-knowledge programmer, I stumbled upon this - until I checked service properties:


Basically, only thing one needs to do is set file permissions through this super-user-friendly screen:


After this, hitting "ENTER" does the trick:


And whoalla - it worked!


utorak, 2. veljače 2010.

Multiple submit buttons on ASP.NET MVC forms


I am currently developing a medium CMS site, and chose to try out ASP.NET MVC, powered by sharp architecture. Before I get to the point, I must say that I am allways amased with any tools that reduce manual and repeating, boring, every-app-the-same coding to minimum, but usually my enthusiasm plumps when I realize that I actually have to write repeating code all the time! Still, with this one I am quite satisfied.

Now, actually getting to a point: what to do when You have to have multiple buttons on a same form and, hopefully, being able to "catch appropriate events" in controller. Here's what I came up with:

Let's start with controller, in which we have two functions, both are actions available in a view "Edit". In a controller, we want to have functions like these:

public ActionResult Filter(string filterString){ ... }

public ActionResult Save(FormCollection form) { ... }

First of all, they are called from a same view, so basically they should have been called the same, "Edit", but luckily, we have an attribute to assign them a real name:

[ActionName("Edit") ]

Now, we still have to tell a submit button which function to "call". It is not actually possible like that, but we can add a parameter to button, or, value:

<button name="button" value="someValue" type="submit">

Next, we somehow have to allow for a controller action to be called only for button we want, thats where this small piece of code jumps in:

public class AcceptSubmitButton : ActionMethodSelectorAttribute
{
public override bool IsValidForRequest
(ControllerContext controllerContext,MethodInfo methodInfo)
{
var req = controllerContext.RequestContext.HttpContext.Request;
return req.Form["button"] == methodInfo.Name;
}
}

And our controller methods should look like:

[ActionName("Edit") , AcceptSubmitButton]
public ActionResult Filter(string filterString){ ... }

[ActionName("Edit") , AcceptSubmitButton]
public ActionResult Save(FormCollection form) { ... }

The problem with this solution is that each time we create a submit button in a view, we have to set name attribute to "button", and value to controller method name (not action name). To take cate that this is done well, we introduce Html extension (namespace is Microsoft.Web.Mvc on purpose so it is included in every view automatically):

namespace Microsoft.Web.Mvc
{
public static class HtmlExtensions
{
public static string ActionSubmitButton(this HtmlHelper helper,string text, string actionName)
{
return "<button name="\" value="\">
+ "\" type=\"submit\">" + text
+ "</button>";
}
}
}
In view, rendering this button looks something like:

<%= Html.ActionSubmitButton("Perform filter", "Filter") %>
<%= Html.ActionSubmitButton("Perform save", "Save") %>

for Filter controller method, and Save method respectively.