views:

46

answers:

3

Hello i am creating a small webpage that give our users an interface to search in our database.

This website must supply 2 webservice functions, Search(string searchString) and GetAccountInfoByInitials(string initials)

I would like to use my controllers to do this, but i can not find out how i can get the html out of a ViewResult.

I have tryed the following, but the result.ToString() only give me the string "System.Web.Mvc.ViewResult"

public class SearchService : ISearchService

{

private readonly ServiceHandlerController _controller;
public SearchService()
{
    _controller = new ServiceHandlerController();
}

public string Search(string searchString)
{
    var result = _controller.Search(searchString);
    return result.ToString();
}

public string GetAccountInfoByInitials(string initials)
{
    var result = _controller.Search(initials).ToString();
    return result;
}

}
A: 

I do this in almost an identical fashion but actually use the controller iteself to return a partialview to string.

i use the following extension method in my base controller:

public static class ExtensionMethods
{
    public static string RenderPartialToString(this ControllerBase controller, string partialName, object model)
    {
        var vd = new ViewDataDictionary(controller.ViewData);
        var vp = new ViewPage
        {
            ViewData = vd,
            ViewContext = new ViewContext(),
            Url = new UrlHelper(controller.ControllerContext.RequestContext)
        };

        ViewEngineResult result = ViewEngines
                                  .Engines
                                  .FindPartialView(controller.ControllerContext, partialName);

        if (result.View == null)
        {
            throw new InvalidOperationException(
            string.Format("The partial view '{0}' could not be found", partialName));
        }
        var partialPath = ((WebFormView)result.View).ViewPath;

        vp.ViewData.Model = model;

        Control control = vp.LoadControl(partialPath);
        vp.Controls.Add(control);

        var sb = new StringBuilder();

        using (var sw = new StringWriter(sb))
        {
            using (var tw = new HtmlTextWriter(sw))
            {
                vp.RenderControl(tw);
            }
        }
        return sb.ToString();
    }
}

followed by then returning my partialview in the following fashion:

return Content(this.RenderPartialToString("myPartialView", myModel));

This should hopefully sort you out.

jim
How do you create the Controller class in your web service? i keep getting a null exception on controller.ControllerContext
DoomStone
DoomStone, my case actually does differ as it's a public api and therefore actually is rolled via the controller, rather than via a webservice. i guees your requirement is slightly different to my implentation in that case... :(
jim
.. just to add, this SO question kinda covers my approach (i.e. using mvc as a RESTful service, rather than using webservices. of course, you may require the security elements of the webservice approach in which case all bets are off. anyway - SO Q -> http://stackoverflow.com/questions/118931/asp-net-mvc-web-services
jim
A: 

The View Result doesn't holds the page by itself. Asp.net MVC uses it, along with the View Engine configured to get the actual page.

You'll hit a roadblock if you are using the default view engine - see link text. Basically because the asp.net view engine is tied to the context. Other view engines won't give you this issue, but if the assets you are trying to reduce are already relying in the default view engine then that defeats the purpose. There are other ways around it, but I'm unsure how convenient those would be for you.

eglasius
A: 

This is an answer to a question I posted similar to this one: http://stackoverflow.com/questions/3702526/is-there-a-way-to-process-an-mvc-view-aspx-file-from-a-non-web-application

public class AspHost : MarshalByRefObject
{
    public string _VirtualDir;
    public string _PhysicalDir;

    public string ViewToString<T>(string aspx, Dictionary<string, object> viewData, T model)
    {
        StringBuilder sb = new StringBuilder();
        using (StringWriter sw = new StringWriter(sb))
        {
            using (HtmlTextWriter tw = new HtmlTextWriter(sw))
            {
                var workerRequest = new SimpleWorkerRequest(aspx, "", tw);
                HttpContext.Current = new HttpContext(workerRequest);

                ViewDataDictionary<T> viewDataDictionary = new ViewDataDictionary<T>(model);
                foreach (KeyValuePair<string, object> pair in viewData)
                {
                    viewDataDictionary.Add(pair.Key, pair.Value);
                }

                object view = BuildManager.CreateInstanceFromVirtualPath(aspx, typeof(object));

                ViewPage viewPage = view as ViewPage;
                if (viewPage != null)
                {
                    viewPage.ViewData = viewDataDictionary;
                }
                else
                {
                    ViewUserControl viewUserControl = view as ViewUserControl;
                    if (viewUserControl != null)
                    {
                        viewPage = new ViewPage();
                        viewPage.Controls.Add(viewUserControl);
                    }
                }

                if (viewPage != null)
                {
                    HttpContext.Current.Server.Execute(viewPage, tw, true);

                    return sb.ToString();
                }

                throw new InvalidOperationException();
            }
        }
    }

    public static AspHost SetupFakeHttpContext(string physicalDir, string virtualDir)
    {
        return (AspHost)ApplicationHost.CreateApplicationHost(
            typeof(AspHost), virtualDir, physicalDir);
    }
}

Then, to render a file:

var host = AspHost.SetupFakeHttpContext("Path/To/Your/MvcApplication", "/");
var viewData = new ViewDataDictionary<SomeModelType>(){ Model = myModel };
String rendered = host.ViewToString("~/Views/MyView.aspx", new Dictionary<string, object>(viewData), viewData.Model);
marq