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?

Rookian
  • 19,841
  • 28
  • 110
  • 180
  • Why not just have the method return different types of `ActionResults` depending on `IsAjaxRequest`? – bzlm Sep 17 '10 at 09:17
  • I side with the OP on this one, I like return new HybridViewResult(). Maybe the naming needs some work. – eglasius Sep 17 '10 at 09:53

4 Answers4

2

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
  • 35,831
  • 5
  • 65
  • 110
  • 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 Sep 17 '10 at 11:02
  • 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 Sep 17 '10 at 11:09
2

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
  • 8,525
  • 5
  • 39
  • 66
  • +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 Sep 17 '10 at 10:47
  • HybridViewResult looks a nicer on the eye, although with NormalOrAjaxResult you've got a more explicit indication of what's being returned. – Castrohenge Sep 17 '10 at 10:52
  • but it can still be named NormalOrAjaxResult and do it automatically / or in this case NormalOrPartialViewResult. – eglasius Sep 17 '10 at 11:11
  • .. 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 Sep 17 '10 at 11:19
  • Thanks very much for the IsAjaxRequest() tip, I never knew about that. Good all round learning experience question. – Castrohenge Sep 17 '10 at 11:27
1

I know I'm really late to the party here, but these didnt seem quite right to me, so here's my 2 cents:

public class PartialViewConverter : ViewResult
{
    public ViewResultBase Res { get; set; }
    public PartialViewConverter(ViewResultBase res) { Res = res; }
    public override void ExecuteResult(ControllerContext context)
    {
        Res.ExecuteResult(context);
    }
    public static ViewResult Convert(ViewResultBase res)
    {
        return new PartialViewConverter(res);
    }
}

With usage:

return PartialViewConverter.Convert(PartialView());

And then in your controller if you override View

protected override ViewResult View(string viewName, string masterName, object model)
{
    //Whichever condition you like can go here
    if (Request.QueryString["partial"] != null)
        return PartialViewConverter.Convert(PartialView(viewName, model));
    else
        return base.View(viewName, masterName, model);
}

Any action method where you return a view will automatically also return partials when requested:

public ActionResult Index()
{
    ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";

    //This will return a partial if partial=true is passed in the querystring.
    return View();
}
major-mann
  • 2,602
  • 22
  • 37
1

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

Stefanvds
  • 5,868
  • 5
  • 48
  • 72