Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Links breaking when View Serialized

I have the following as part of a View Model that populates a partial view:

public string DownloadLink
{
    get
    {
        UrlHelper url = new UrlHelper(HttpContext.Current.Request.RequestContext);
        switch (this.Type)
        {
            case (int)DocumentTypes.WasteNote: { 

                return url.Action("PaperWork", "Jobs", new { JobId = this.DOCJobId }, HttpContext.Current.Request.IsSecureConnection ? "https" : "http" ); 
            }
            case (int)DocumentTypes.Contract:
            case (int)DocumentTypes.DestructionCert:
            case (int)DocumentTypes.Quote:
            default: { return url.Action("Download", "Documents", new { DocId = this.DocumentLinkId }, HttpContext.Current.Request.IsSecureConnection ? "https" : "http"); }
        }
    }
}

Called in the View thus:

@model  IEnumerable<Document>
@using CustomerDashboard.ViewModels;
@using CustomerDashboard.Utilities;
@{ Layout = null; }
    @foreach (Document doc in Model)
    {
        <li>
            <a href="@doc.DownloadLink" class="documentDownload">
                <div class="col-sm-12 col-md-5 li-row li-row-icon">
                    <div class="pull-left">
                        <img height="40" src="/Content/img/file-icons/@doc.Icon" />
                    </div>
                    ...
             </a>
        </li>
    }

Whilst this is rendered directly in another View the link generated is fine, however, I'm serializing the partial and returning as JSON:

public string RenderRazorViewToString(string viewName, object model)
    {
        //https://gist.github.com/timiles/2828976 
        ViewData.Model = model;
        using (var sw = new StringWriter())
        {
            var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext,
                                                                     viewName);
            var viewContext = new ViewContext(ControllerContext, viewResult.View,
                                         ViewData, TempData, sw);
            viewResult.View.Render(viewContext, sw);
            viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
            return sw.GetStringBuilder().ToString();
        }
    }

It's then returned as Json from the controller:

        return Json(new { 
            totalCount = (int)Session["DocumentTotalCount"], 
            markup = RenderRazorViewToString("_DocumentListAjax", docs) 
        },JsonRequestBehavior.AllowGet);

To be clear though, the problem is happening before the JSON serialization - this is nasty but removes the www prefix:

        return Json(new { 
            totalCount = (int)Session["DocumentTotalCount"], 
            markup = RenderRazorViewToString("_DocumentListAjax", docs).Replace("www.","") 
        },JsonRequestBehavior.AllowGet);

When doing this, from what appears to be from outside the LAN (which sounds odd), all the urls have www prepended - ie https://example.com becomes https://www.example.com. I'm struggling to track down why this is happening and how to fix it.

like image 444
SWa Avatar asked Aug 14 '15 12:08

SWa


People also ask

What are the disadvantages of serialization?

But the constructor of the class remains uncalled. This results in a variation of Java Standard Flow. This process is inefficient when it comes to memory utilization. Serialization is not useful in applications that need concurrent access without using third party APIs.

Why is serialization not good?

Serialization is brittle, it pokes into private field, violates constructor invariance, it's horrible in so many ways. The only thing appealing about it is that it's easy to use in simple use cases. That's what motivated getting it in there. But now, we do have to get it out."

Why does serialization adversely affect?

The main problem with Java Serialization is performance and efficiency. Java serialization is much slower than using in memory stores and tends to significantly expand the size of the object. Java Serialization also creates a lot of garbage.

Why is binary formatter unsafe?

BinaryFormatter uses violates 2.), which is a huge security risk because it makes possible to run any code.


1 Answers

With your code, the described behavior can only occur when servicing different requests. Rendering of the partial view inside another view must happen as a result of handling an http request whose context's host is set to example.com (e.g a request to https://example.com/viewWithAPartialView).

Serving JSON containing a partial view, on the other hand is done as a result of handling a request to www.example.com (e.g. a request to https://www.example.com/getPartialViewJson/partialViewName).

Since rendering the partial view inside its master view is probably done when browsing the website via its "normal" url - everything goes as planned.

The JSON endpoint might be queried via AJAX, check the code that forms the request - it is the culprit. Another possibility is that you have URL rewriting set up to strip the www prefix, and for some reason the rewriting rule does not match the JSON serving endpoint.

Update:

Given the additional information it looks like the issue can be related to hosting configuration (IIS and load balancer settings). What I can suggest is to try to add the following line to your web.config file:

<appSettings>
  ...
  <add key="aspnet:UseHostHeaderForRequestUrl" value="true" />
  ...
</appSettings>

This will force ASP.NET to use the host header from incoming requests instead of asking for a server name variable. If the cause of the issue is indeed a configuration problem this should help.

like image 196
Roman Pletnev Avatar answered Sep 28 '22 14:09

Roman Pletnev