MVC JSON ActionResult returns all page HTML output

Posted by Community Admin on 04-Aug-2018 01:15

MVC JSON ActionResult returns all page HTML output

All Replies

Posted by Community Admin on 17-Oct-2012 00:00

When MVC widgets are added to templates in sitefinity, controller calls posted to ActionResults from jQuery or in my case Kendo MVC components return the JsonResult followed by the entire View output.
For example I have a simple Kendo Grid wired up to CRUD JSON ActionResult methods in the controller.  The grid and actions work as expected in a standard MVC project...

Here is the Read Method as an example:

[HttpPost]
public ActionResult GetCompanies([DataSourceRequest]DataSourceRequest request)
    var entities = (from c in db.Companies
                    select c).ToList();
 
    DataSourceResult result = entities.ToDataSourceResult(request);
    return Json(result);

In a standard MVC Project when viewing the results in Firebug are:

"Data":["CompanyId":1,"CompanyName":"123Company","Locations":[],"CompanyId":6,"CompanyName":"678 Company","Locations":[],"CompanyId":10,"CompanyName":"456 Company","Locations":[]],"Total":3,"AggregateResults":null,"Errors":null

Here are the results using the exact same code in Sitefinity (truncated the output to save space as the output is the entire index output):

"Data":["CompanyId":1,"CompanyName":"123Company","Locations":[],"CompanyId":6,"CompanyName":"678 Company","Locations":[],"CompanyId":10,"CompanyName":"456 Company","Locations":[]],"Total":3,"AggregateResults":null,"Errors":null
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><meta name="Generator" content="Sitefinity 5.1.3450.0 CE" /><link href="/SFRepWeb/Telerik.Web.UI.WebResource.axd?compress=0&_TSM_CombinedScripts_=%3b%3bTelerik.Sitefinity.Resources%2c+Version%3d5.1.3450.0%2c+Culture%3dneutral%2c+PublicKeyToken%3dnull%3aen%3aa14cc7f5-9d82-48ad-8683-c9402ebc4a01%3a7a90d6a%3ad271177c%3adff30785" type="text/css" rel="stylesheet" /><title>
    test123
</title></head>
<body>
    <form method="post" action="" id="aspnetForm">
<div class="aspNetHidden">
<input type="hidden" name="ctl12_TSM" id="ctl12_TSM" value="" />
<input type="hidden" name="ctl13_TSSM" id="ctl13_TSSM" value="" />
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
------- OUTPUT TRUNCATED ---------------------------------------

You can see that it is basically returning the JSON result first followed by the controllers index cshtml output. This is causing Kendo Components to either not render or parse when all they expect is JSON, return null parameters on CRUD method executions, etc.

I assume this is the result of some interferance with MVC operations in order to support MVC within Sitefinity which by the way I think is great. 
If so is there any kind of Attribute that can be put on methods to tellSitefinity not to output the page and only the returned results?
Is there any way to prevent this from happening, or also am I doing something wrong that I am not aware of?

Posted by Community Admin on 17-Oct-2012 00:00

Found another article that suggested from the documentation that
explained how to run a controller in classic mode.  At first I thought
this would be an issue, but as it turns out it was a good suggestion and
works great to prevent full page output where we only want JSON.

Basically I just created a Global.asax in my sitefinity project.  And put the following in the Application_Start method...

protected void Application_Start(object sender, EventArgs e)
    Bootstrapper.MVC.MapRoute(
        "Classic",
        "JSON/controller/action",
        new action = "Index" );

Now when making requests using the Kendo framework, jQuery etc that expect JSON results to be returned we need to just prepend JSON in the URL.

Here is an example Kendo grid overriding the action method to post correctly.

@(Html.Kendo().Grid<Company>()
    .Name("Companies")
    .ToolBar(tb =>
        tb.Create();
        tb.Save();
    )
        .Editable(editable => editable.Mode(GridEditMode.InCell))
        .Pageable()
        .Navigatable()
        .DataSource(dataSource => dataSource.Ajax()
        .Batch(true)
        .ServerOperation(false)
        .Model(model => model.Id(p => p.CompanyId))
        .Read(create => create.Url("./JSON/Company/GetCompanies"))
        .Update(update => update.Url("./JSON/Company/UpdateCompany"))
        .Create(insert => insert.Url("./JSON/Company/InsertCompany"))
        .Destroy(destroy => destroy.Url("./JSON/Company/DeleteCompany"))
    )
    .Columns(cols =>
    
        cols.Bound(c => c.CompanyName);
        cols.Command(cmd =>
        
            cmd.Edit();
            //  cmd.Destroy();
        );
    )
  )






Posted by Community Admin on 09-Nov-2012 00:00

I font another way to fix this , you just need to
1.Add a boolean with default value false in the controller.
2.Set the value to true in every method which returns json.
3.Override the OnResultExecuted method and call Response.End() if the boolean is true.

you get only json in the response.

Posted by Community Admin on 13-Nov-2012 00:00

Thanks Mihail. Telerik told me they are working on a fix for this.

Posted by Community Admin on 05-Apr-2013 00:00

Mihaul's suggestion worked great for me. I posted some code to help:

In my controller with the JsonResponse:
protected override void OnResultExecuted(ResultExecutedContext ctx)

// if we have a JSON result to return do not allow OnResultExecuted to execute or it will return unwanted results (HTML markup)
            if (isJsonReturn) Response.End();
            base.OnResultExecuted(ctx);


My Controller function returning Json:
[HttpPost]
public JsonResult BuildJsonString(MenuModel model)

            // setting isJsonReturn to true will enable this method to return JSON and disable all sitefinity functionality from here forward
            isJsonReturn = true;

            MenuModel menu = new MenuModel();
            menu.Item = "item1";
            return Json(menu);


jQuery in the View:
                $.ajax(
                    type: 'POST',
                    url: '/Menu/BuildJsonString',
                    cache: false,
                    dataType: 'json',
                    contentType: 'application/json; charset=utf-8',
                    data: JSON.stringify( Item: "item1" ),
                    success: function (response)
                        console.log(JSON.stringify(response));
                    ,
                    error: function (response)
                        console.log(JSON.stringify(response));
                   
                );

Posted by Community Admin on 10-Apr-2013 00:00

Hi,

Thank you for sharing your solutions and workarounds with the community in this forum thread. We got a couple of reports of this improper behavior and we have identified it to be a bug. It is logged for fixing. We will do our best to fix the bug as soon as possible.

Regards,
Stefani Tacheva
the Telerik team

Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items

Posted by Community Admin on 28-Apr-2013 00:00

Thanks, all i need:

protected override void OnResultExecuted(ResultExecutedContext ctx)     

        if (Request.IsAjaxRequest())          
              Response.End();
    
        base.OnResultExecuted(ctx);

Posted by Community Admin on 29-Apr-2013 00:00

Hello Trung,

Thank you for sharing your source code and solution here.

Regards,
Stefani Tacheva
the Telerik team

Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items

Posted by Community Admin on 20-Sep-2013 00:00

:( i still get the whole Page returning if i use the Content method, and only errors if i use the JSON one , I'm assuming the error is due to invalid JSON? (the widget is on a page called hyweltest)

.net
    public class TestController : Controller
   
        public int Number get; set;
        public string Name get; set;
               
        protected override void OnResultExecuted(ResultExecutedContext ctx)
       
            if (Request.IsAjaxRequest())
                Response.End();
            base.OnResultExecuted(ctx);
       

        [HttpPost]
        public ActionResult ContentTest(TestModel model)
       
            return Content(<string containing valid JSON>);
       

        [HttpPost]
        public JsonResult AJAXTest(TestModel model)
       
            return Json(model,JsonRequestBehavior.AllowGet);
       

javascript
      
  var actionURL = pageURI + '/AJAXTest',
        actionURL = '/hyweltest/AJAXTest';
        
        $.ajax(
            type: 'POST',
            url: actionURL,
            cache: false,
            dataType: 'json',     
            contentType: 'application/json; charset=utf-8',
            data: JSON.stringify(mvvmWrapper.model),
            success: function (response)
                alert("Success");
            ,
            error: function (response)
                alert("Fail");
           
        );

Any help on this would be most apprecieated

Posted by Community Admin on 20-Sep-2013 00:00

FYI, the result i get back in my error response is the following - it looks like the rest of the page is "wrapping" the json.

"readyState":4,"responseText":"\r\n\r\n\r\n

<meta name='\"Generator\"' content='\"Sitefinity' version\"="" trial="" pu="" 6.1.4600.0="">
<link href='\"/Telerik.Web.UI.WebResource.axd?compress=0&amp;_TSM_CombinedScripts_=%3b%3bTelerik.Sitefinity.Resources%2c+Version%3d6.1.4600.0%2c+Culture%3dneutral%2c+PublicKeyT3\"' rel='\"stylesheet\"' type='\"text/css\"'>
<link href='\"/Sitefinity/WebsiteTemplates/MyTheme1/App_Themes/MyTheme1/global/Reset.css?v=634798559040000000\"' rel='\"stylesheet\"' type='\"text/css\"'>
<link href='\"/Sitefinity/WebsiteTemplates/MyTheme1/App_Themes/MyTheme1/global/Layout.css?v=635150288835325922\"' rel='\"stylesheet\"' type='\"text/css\"'>
<title>\r\n\tHywelTest\r\n</title>\r\n\r\n    
<form id='\"aspnetForm\"' action='\"AJAXTest\"' method='\"post\"'>
<div class='\"aspNetHidden\"'>
<input name='\"ctl08_TSM\"' id='\"ctl08_TSM\"' type='\"hidden\"' value='\"\"'>
<input name='\"ctl09_TSSM\"' id='\"ctl09_TSSM\"' type='\"hidden\"' value='\"\"'>
<input name='\"__EVENTTARGET\"' id='\"__EVENTTARGET\"' type='\"hidden\"' value='\"\"'>
<input name='\"__EVENTARGUMENT\"' id='\"__EVENTARGUMENT\"' type='\"hidden\"' value='\"\"'>
<input name='\"__VIEWSTATE\"' id='\"__VIEWSTATE\"' type='\"hidden\"' value='\"/wEPDwUKMTg3ODYyNzE1N2QYAQUeX19Db250cm9sc1JlcXVpcmVQb3N0QmFja0tleV9fFgEFH2N0bDExJGN0bDAwJGN0bDAwJHdpbmRvd01hbmFnZXJpoXZ24sm/kczFSXtvy19fbwE5VuMeRqImXPTviRKSAw==\"'>
<input name='\"ctl08\"' id='\"ctl08\"' type='\"hidden\"'>
<div class='\"sfPublicWrapper\"' id='\"PublicWrapper\"'>
<div class='\"sf_cols\"'>
<div class='\"sf_colsOut' sf_2cols_1_75\"="">
<div class='\"sf_colsIn' id='\"T27B2843A001_Col00\"' sf_2cols_1in_75\"="">

\"Number\":234234234,\"Name\":\"fsgdfgsdfgsgf\",\"JSONString\":\"\\\"Name\\\":\\\"fsgdfgsdfgsgf\\\",\\\"Number\\\":234234234\"","status":200,"statusText":"OK"

</div></div></div></div></form>

Posted by Community Admin on 20-Sep-2013 00:00

The above method did not work for me, so A Horrible work around.......
 [HttpPost]
        public JsonResult AJAXTest(TestModel model)
       
            Response.Clear();
            Response.Write(<JSON STRING>);
            Response.End();
            return null;
       

Hope this helps others to avoid the pain i have been feeling for over 48 hours....... Sitefinity team, please can you fix the underlying bug, so i can make my code pretty again!!!!!

Posted by Community Admin on 24-Sep-2013 00:00

Hywel, what version of Sitefinity are you using? I wonder if the previously mentioned fixes have stopped working in SF6.1.

Posted by Community Admin on 24-Sep-2013 00:00

I am on 6.1

Posted by Community Admin on 24-Sep-2013 00:00

OK, that explains it then. For some reason the fix has stopped working in 6.1. Any ideas Stefani?

Posted by Community Admin on 25-Sep-2013 00:00

Hello,

The other workaround I can offer is to use classic MVC mode and register a custom route. You can directly route to your controller, and take Sitefinity out of the picture.

Here is how you can register a route with a custom prefix (in your Global.asax Application_Start method):

Bootstrapper.MVC.MapRoute(
                "Json",
                "json/controller/action/id",
                new controller = "JsonController", action = "Json", id = (string)null
            );

After you've done this you can access your controller directly through the URL http://your-site-domain/json/<controller>/<action>. Note that the route has a prefix ("json/"), which needs to be there to distinguish it from normal Sitefinity pages.

When you substitute the real name of the controller and action, it will be executed and the JSON result will be returned.

Regards,
Stefani Tacheva
Telerik
Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items

Posted by Community Admin on 25-Sep-2013 00:00

Thanks but I need it to work in Hybrid mode!

Posted by Community Admin on 25-Sep-2013 00:00

So it looks like SF6.1 puts the html first and then the JSON which stops the fix working.  I've come up with this alternative fix:

protected override void OnActionExecuting(ActionExecutingContext filterContext)
    if (Request.IsAjaxRequest())
        Response.Clear();
 
    base.OnActionExecuting(filterContext);
 
protected override void OnResultExecuted(ResultExecutedContext filterContext)
     if (Request.IsAjaxRequest())
        Response.End();
 
    base.OnResultExecuted(filterContext);

This works for me in SF6.1. Anyone see an issue with this?

Thanks,

Stuart

Posted by Community Admin on 27-Sep-2013 00:00

Hi, I am still very new to Sitefinity,

Can anyone please let me know if they are confident that it properly and robustly supports MVC?

Everything I have tried in so far seems like a bit of a hack!

Posted by Community Admin on 27-Sep-2013 00:00

If you can avoid it, it might be best. I can't find answers to the problems I've encountered.

Posted by Community Admin on 27-Sep-2013 00:00

This doesn't work at all for me unfortunately.

Posted by Community Admin on 30-Sep-2013 00:00

Isn't there something we can do to make this work? This thread is a year old and nothing in here seems to work. 

Posted by Community Admin on 01-Oct-2013 00:00

Hey Chris, could you post your code for the controller?

Posted by Community Admin on 03-Oct-2013 00:00

I fixed this. The issue was related to OpenAccess and json serialization. The OnResultExecuted would never fire and the action would hang indefinitely.

Posted by Community Admin on 08-Jul-2014 00:00

To Hywel. We have been fighting with Sitefinity to make MVC work and its a mess. They are on the right track but not there yet.

This thread is closed