There are three modes for working with MVC in Sitefinity. The difference is that Sitefinity’s MVC support allows multiple controllers on a Sitefinity page versus classic MVC using only one controller. This may cause problems when a controller performs a postback and navigates to an action.
Example
- FirstController has actions Index and IndexPostBack
- SecondController has actions Load and LoadPostBack
Both controllers are placed on a Sitefinity hybrid page, allowing for MVC widgets and WebForms widgets. FirstController performs a postback, which changes the URL to http://site.com/page/IndexPostBack.
SecondController is not rendered on this URL because the action Load
is not available for the route http://site.com/page/IndexPostBack.
Solution
To overcome this, I provide a sample of two MVC widgets performing postbacks asynchronously. Refer to the attached sample for the code.
There are two controllers: the first for creating News and the second for creating Events (CreateNewsController and EventsController).
Upon postback, the controllers create Sitefinity Event/News items.
[HttpPost]
public
ActionResult Create(CreateNewsModel model)
{
if
(ModelState.IsValid)
{
var manager = NewsManager.GetManager();
var newsItem = manager.CreateNewsItem();
newsItem.Title = model.Title;
newsItem.Content = model.Content;
newsItem.Author = model.Author;
manager.SaveChanges();
Dictionary<
string
,
string
> contextBag =
new
Dictionary<
string
,
string
>();
WorkflowManager.MessageWorkflow(newsItem.Id,
typeof
(NewsItem), manager.Provider.Name,
"Publish"
,
true
, contextBag);
return
Content(MvcHelper.RenderPartialViewToString(
this
,
"_NewsCreated"
,
null
));
}
return
Content(MvcHelper.RenderPartialViewToString(
this
,
"Default"
, model));
}
Under normal conditions, the postback redirects to a new route, and in this case, it goes to http://site.com/page/Create. This hides all other widgets since they are unavailable for this route.
The control handles this redirect to another route by performing an async postback. When creating a news/event item, the result of the postback loads two partial views (_NewsCreated.cshtml and _EventCreated.cshtml) through the MvcHelper
class.
public
class
MvcHelper
{
public
static
string
RenderPartialViewToString(Controller controller,
string
viewName,
object
model)
{
if
(
string
.IsNullOrEmpty(viewName))
viewName = controller.ControllerContext.RouteData.GetRequiredString(
"action"
);
controller.ViewData.Model = model;
using
(var sw =
new
StringWriter())
{
var viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
var viewContext =
new
ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
viewResult.View.Render(viewContext, sw);
return
sw.GetStringBuilder().ToString();
}
}
}
The async postback is performed client-side by the script NewsScript/EventScript.js.
//check if Create ActionResult is called
$(document).ready(
function
() {
$(
"#createNews"
).click(
function
(){
var
model = NewsObject.collectModel();
NewsObject.sendData(model,
"/"
+ CURRENTPAGE +
"/Create"
,
"myNewsForm"
);
}
);
});
//perform async POST
sendData:
function
(newsData, destination, resultHolderId) {
$.ajax({
type:
'POST'
,
url: destination,
contentType:
'application/json; charset=utf-8'
,
data: JSON.stringify(newsData),
success:
function
(result, args) {
$(
"#"
+resultHolderId).html(result)
},
error:
this
._syncFailureDelegate
});
}
}
Stanislav Velikov
Stanislav Velikov is a Tech Support Engineer at Telerik. He joined the Sitefinity Support team in April 2011.