I have code that does a simple form post in a new window from our web application that calls out to an Action on a ASP.NET MVC3 Controller. This behavior works just fine on PC Browsers but if a user is on a Mac the form post causes the browser to download a Zero byte file with the name of the Action that is being requested.
The action looks up an item from the database and based on its Format returns a FileContentResult with the correct content type and the item's data.
Can anyone tell me why this is happening and any workarounds they've found when running into this?
if (item.Format == PrintedItemFormat.PDF || item.Format == PrintedItemFormat.XDP)
{
return new FileContentResult(Encoding.UTF8.GetBytes(item.Data), "application/vnd.adobe.xdp+xml");
}
if (item.Format == PrintedItemFormat.XFDL)
{
return new FileContentResult(Encoding.ASCII.GetBytes(item.Data), "application/vnd.xfdl");
}
if (item.Format == PrintedItemFormat.CSV)
{
return new FileContentResult(Encoding.UTF8.GetBytes(item.Data), "application/CSV")
{
FileDownloadName = item.FileName
};
}
if (item.Format == PrintedItemFormat.HTML)
{
return new FileContentResult(Encoding.UTF8.GetBytes(item.Data), "text/html");
}
if (item.Format == PrintedItemFormat.TXT)
{
return new FileContentResult(Encoding.UTF8.GetBytes(item.Data), "text/plain");
}
if (item.Format == PrintedItemFormat.XFDF)
{
return new FileContentResult(Encoding.UTF8.GetBytes(item.Data), "application/vnd.adobe.xfdf");
}
I think the problem is the Mac browsers need to know a FileDownloadName as it cannot be inferred via the request.
Related
I am having a problem with return this.View("Index",model) (after the database processing) refreshing the browser when I upload an 80Mb file. The code works fine on smaller files. The code also works when I upload an 80Mb file with the debugger attached to w3wp.exe and manually step through it. I have tried multiple browsers and have the same problem across all of them.
[HttpPost]
public ActionResult Index(ImportDataViewModel model)
{
string importFileLoc = string.Empty;
if (Request.Files.Count != 0)
{
importFileLoc = this.SaveTempFile(Request.Files[0]);
}
if (!this.ValidateImportModel(model))
{
model.SystemNames = this.GetSystemNames().SetSelected(model.SelectedSystem);
return this.View(model);
}
// Do Database and other data processing here
if (!ModelState.IsValid || model.ContainsWarnings)
{
model.SystemNames = this.GetSystemNames(model.SelectedSystem);
return this.View("Index", model);
}
return this.RedirectToAction("Index");
}
I'm using
<img src="#Url.Action("getImage", "AccessFile", new { imagePath= #ViewData["imagePath"] })"/>
in the View to display image that exists as a local file in the server.
getImage action in AccessFileController will look like
public ActionResult getImage(string imagePath)
{
if (!System.IO.File.Exists(imagePath))
{
//Log
return ?????????
}
else
{
return base.File(imagePath, "image/jpg");
}
}
My question is, what should I put in ????????? to allow user to see some kind of error message?
I tried
return new HttpNotFoundResult();
return RedirectToAction("ExpectedError", "Error");
but it only returns empty image with a broken icon on it.
Any good solution?
You can show a predefined image for empty request,
return Content(imagePath2);
or you can show a javascript which then you can show an error
return Content("<script language='javascript' type='text/javascript'>alert('Image not found!');</script>");
In Sitecore 7, it is now possible to create model definition items under /sitecore/layout/Models and link them to my Layouts and Renderings (as opposed to hard-coding the type + assembly on each one). This makes it much easier to manage, especially if I ever need to update my namespaces or see which layouts are using a particular model.
That said, I have hit an issue whereby Glass.Mapper appears to parse the 'Model' field as though it is a text field, when it is in fact an Internal Link field. Here is the error I am getting:
Could not load type '/sitecore/layout/Models/HomeViewModel' from
assembly 'Glass.Mapper.Sc, Version=3.0.2.8, Culture=neutral,
PublicKeyToken=null'.
Does anyone now if Glass supports linking to Models in Sitecore 7, or am I correct to assume that it's just not resolving the Internal Link field to the Model?
UPDATE: This works properly now in the latest version, none of what I said below is needed anymore, keeping for posterity's sake.
I ran into this problem myself and unfortunately it does not appear as if this is supported. I looked on the Trello for Glass and it looks like Sitecore 7 testing/support is an upcoming task although it mostly works in its current form aside from one or two issues.
That being said since it's open source it's not too much of a hassle to get it working yourself. Below is the full code for the Glass.Mapper.Sc.Pipelines.Response.GetModel class which I've modified to resolve two issues I was having
The issue you've mentioned
Extending the class to allow for automatically using the DataSource instead of the context item to generate the model. I've included a comment in the code to let you know how to disable this portion of the file, because it relies on another change elsewhere in the library (but I can provide that as well if you'd like).
Please note that I have not modified all methods in this class, just the ones that have broken for me so far. The modifications themselves are fairly straightforward (just make it look for the linked item instead of a text field). I hope this helps.
public class GetModel : GetModelProcessor
{
public GetModel()
{
ContextName = "Default";
}
public string ContextName { get; set; }
public override void Process(GetModelArgs args)
{
if (args.Result == null)
{
Rendering rendering = args.Rendering;
if (rendering.RenderingType == "Layout")
{
args.Result = GetFromItem(rendering, args);
if (args.Result == null)
{
args.Result = GetFromLayout(rendering, args);
}
}
if (args.Result == null)
{
args.Result = GetFromPropertyValue(rendering, args);
}
if (args.Result == null)
{
args.Result = GetFromField(rendering, args);
}
}
}
protected virtual object GetFromField(Rendering rendering, GetModelArgs args)
{
Item obj = ObjectExtensions.ValueOrDefault<RenderingItem, Item>(rendering.RenderingItem, (Func<RenderingItem, Item>)(i => i.InnerItem));
if (obj == null)
return (object)null;
Item model = MvcSettings.GetRegisteredObject<ItemLocator>().GetItem(obj["Model"]);
if (model == null)
return (object)null;
else
return GetObject(model["Model Type"], rendering);
}
protected virtual object GetFromPropertyValue(Rendering rendering, GetModelArgs args)
{
string model = rendering.Properties["Model"];
if (StringExtensions.IsWhiteSpaceOrNull(model))
return (object)null;
else
return GetObject(model, rendering);
}
protected virtual object GetFromLayout(Rendering rendering, GetModelArgs args)
{
string pathOrId = rendering.Properties["LayoutId"];
if (StringExtensions.IsWhiteSpaceOrNull(pathOrId))
return (object)null;
string modelItemPath = ObjectExtensions.ValueOrDefault<Item, string>(MvcSettings.GetRegisteredObject<ItemLocator>().GetItem(pathOrId), (Func<Item, string>)(i => i["Model"]));
string model = ObjectExtensions.ValueOrDefault<Item, string>(MvcSettings.GetRegisteredObject<ItemLocator>().GetItem(modelItemPath), (Func<Item, string>)(i => i["Model Type"]));
if (StringExtensions.IsWhiteSpaceOrNull(model))
return (object)null;
else
return GetObject(model, rendering);
}
protected virtual object GetFromItem(Rendering rendering, GetModelArgs args)
{
string model = ObjectExtensions.ValueOrDefault<Item, string>(rendering.Item, (Func<Item, string>)(i => i["MvcLayoutModel"]));
if (StringExtensions.IsWhiteSpaceOrNull(model))
return (object)null;
else
return GetObject(model, rendering);
}
public object GetObject(string model, Rendering rendering)
{
if (model.IsNullOrEmpty())
return null;
var type = Type.GetType(model, true);
if (type == null)
return null;
var context = Context.Contexts[ContextName];
if (context == null) throw new MapperException("Failed to find context {0}".Formatted(ContextName));
if (context.TypeConfigurations.ContainsKey(type))
{
ISitecoreContext scContext = new SitecoreContext(context);
//comment this if block out if you just need to solve the model link problem
if (rendering != null)
{
if (rendering.Item != null)
{
var dataSourceResult = scContext.GetCurrentItem(type, itemOverride: rendering.Item);
return dataSourceResult;
}
}
var result = scContext.GetCurrentItem(type);
return result;
}
return null;
}
}
I am setting an error Message in the viewbag to show to the user after each postback how ever I do not want to show this error message on page reload or refresh. I have tried to set it to null but it still is shown because the json parameter still contains the values of the first submit.
[HttpPost]
[CustomAuthorize(Definitions.RoleAnalystManager, Definitions.RoleProjectManager)]
public ActionResult ExportReportAllMediaDetailsCsv(string json)
{
ViewBag.Error = null;
var serializer = new JavaScriptSerializer();
var reportParams = serializer.Deserialize<ReportAllMediaDetailsParams>(json);
var rows = uow.Items.Report_AllMediaDetails(reportParams.profileID, reportParams.organisationID, reportParams.startDate, reportParams.endDate).ToList();
if (rows.Count <= 1)
{
ViewBag.Error = "There were no results for the provided parameters, please adjust the parameters and try again.";
return View("AllMediaDetails");
}
This is because refreshing the page actually resubmits the previous request, so your POST request is resubmitted by the browser. Can't test this at the minute; however, perhaps try setting a bool - TempData["FirstLoad"] - to true on the GET request and then do something like this in the POST method:
if (TempData["FirstLoad"] != null && TempData["FirstLoad"] == true)
{
if (rows.Count <= 1)
{
ViewBag.Error = "...";
}
}
else
{
ViewBag.Error = null;
return View();
}
TempData["FirstLoad"] = false;
return View("AllMediaDetails");
I'm basing this on the fact that TempData is stored in the session, so its values should be retained on a refresh (rather than resubmitted as they were originally as if the value was passed as, for example, a hidden field).
I want to call the JavaScript function for counting the selected checkbox and in this function I have to call one statement for call the actionresult method of controller and perform to some function as active user and deactive user and return view() at end
Here is my code:
if (state == "Dec") {
alert("Hello..Dear..you are DeActive");
$.post('#Url.Action("UserDeactive","Admin", new{})' + '?Id=' + strvalue);
}
This statement works well in the normal project when I run project by press the F5, also using VS localhost.
But when I host my project in IIS, for accessing in LAN, this is not work hold java script call but this statement are not call and not navigate to action result method ..for do some function..!
so please me ...All My Dear..! if you have any idea .!
this is my Controller Method:-
public ActionResult UserActive(string Id)
{
int[] numbers = Id.Split(',').Select(n => int.Parse(n)).ToArray();
if (numbers != null)
{
foreach (int id in numbers)
{
User_Master u_master = db.User_Masters.Find(id);
if (u_master.Is_active == "false")
{
u_master.Is_active = "true";
db.Configuration.ValidateOnSaveEnabled = false;
db.SaveChanges();
}
}
}
return RedirectToAction("Dashboard", "Home");
}
Use the second argument of the $.post() method which allows you to POST additional parameters to the server:
var url = '#Url.Action("UserDeactive", "Admin")';
$.post(url, { id: strvalue }, function(result) {
// handle the result of the AJAX call
});