views:

94

answers:

3

Is it possible to build a hybrid ViewResult that returns in depedency of an AjaxRequest or HttpRequest a PartialViewResult or ViewResult?

IsAjaxRequest --> return PartialViewResult !IsAjaxRequest --> return ViewResult

As far as I know my HybridViewResult should derive from ViewResultBase.

But how to implement the FindView method?

+1  A: 

can you not just make 2 different actions in that case? the 'shared' logic you could simply put in a [nonAction] method?

Stefanvds
I do not unterstand you, could you explain your idea more in detail?
Rookian
+2  A: 

Try:

public class HybridViewResult : ActionResult
{
    public string ViewName { get; set; }
    public HybridViewResult () { }
    public HybridViewResult (string viewName ) { this.ViewName = viewName ; }
    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null) throw new ArgumentNullException("context");
        var usePartial = ShouldUsePartial();
        ActionResult res = GetInnerViewResult(usePartial);
        res.ExecuteResult(context);
    }
    private ActionResult GetInnerViewResult(bool usePartial)
    {
        var view = ViewName;
        ActionResult res;
        if(String.IsNullOrEmpty(view)) {
             res = usePartial ? new PartialViewResult(view) : new ViewResult(view);
        }
        else {
             res = usePartial ? new PartialViewResult() : new ViewResult();
        }
        return res;
    }
    private bool ShouldUsePartial(ControllerContext context) {
        return false; //your code that checks if you need to use partial here
    }
}

Add any constructor & GetInnerViewResult variations as needed i.e. to pass Model.

eglasius
when no view name is specified do I have to get the view name manually or does ASP.NET MVC automatically get the view name?
Rookian
afaik that's determined in .ExecuteResult from the ControllerContext / route values (namely action), so yes - but I haven't tested it. / That code was from the top of my head based on what I know of all those pieces.
eglasius
+2  A: 

This is a slightly more stripped down take on eglasius's answer. I'm actually tackling a similar problem except I need to return a JsonResult.

The (untested) NormalOrAjaxResult simply lets you specify an action result for the non ajax request and one for the ajax request. Because these are ActionResults you can mix up Redirect, View, Partial and Json view results.

public class NormalOrAjaxResult : ActionResult
{
    private readonly ActionResult _nonAjaxActionResult;
    private readonly ActionResult _ajaxActionResult;

    public NormalOrAjaxResult(ActionResult nonAjaxActionResult, ActionResult ajaxActionResult)
    {
        _nonAjaxActionResult = nonAjaxActionResult;
        _ajaxActionResult = ajaxActionResult;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        var isAjaxRequest = context.HttpContext.Request["isAjax"];
        if (isAjaxRequest != null && isAjaxRequest.ToLower() == "true")
        {
            _ajaxActionResult.ExecuteResult(context);    
        } else
        {
            _nonAjaxActionResult.ExecuteResult(context);
        }
    }
}
Castrohenge
+1 although personally I like return new HybridViewResult() more than return HybridViewResult(View(), PartialView()). Also with a controller base, it can be return HybridView() :)
eglasius
HybridViewResult looks a nicer on the eye, although with NormalOrAjaxResult you've got a more explicit indication of what's being returned.
Castrohenge
but it can still be named NormalOrAjaxResult and do it automatically / or in this case NormalOrPartialViewResult.
eglasius
@Kieranmaine... for checking of the ajax request use context.HttpContext.Request.IsAjaxRequest() and your strings gonna fly away xD, your approach is also good, but I would prefere the hybrid ViewResult :)
Rookian
Thanks very much for the IsAjaxRequest() tip, I never knew about that. Good all round learning experience question.
Castrohenge