How to enable support of page orientation in itext html2pdf using CSS page rule - itext

We have HTML's for which we incorporate print layouts with mixed landscape and portrait pages. The page orientation is applied with the page rules to keep it clean and maintainable.
It seems html2pdf is completely ignoring this, as per example:
<html>
<head>
<title>UnitTest</title>
<style type="text/css">* {
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
}
#page page-portrait {
size: A4;
orientation: portait;
}
#page page-landscape {
size: A4;
orientation: landscape;
}
.page-portrait {
page-break-after: always;
page: page-portrait;
}
.page-landscapes {
page-break-after: always;
page: page-landscape;
}
</style>
</head>
<body>
<div class="page-portrait">
<p>This should be a portrait page</p>
</div>
<div class="page-landscapes">
<p>This should be a landscape page</p>
</div>
<div class="page-portrait">
<p>This should be a portrait page</p>
</div>
<div class="page-landscapes">
<p>This should be a landscape page</p>
</div>
</body>
</html>

pdfHTML does not support named pages at the moment. Your HTML code also has inconsistency: you expect the following block to be on a landscape page
<div class="page-landscapes">
<p>This should be a landscape page</p>
</div>
While after your previous (portrait) block you do a page break to a portrait page.
Odd-even landscape/portrait pages via pdfHTML
If your goal is to have alternating landscape and portrait pages, you can use an approach like this:
<html>
<head>
<title>UnitTest</title>
<style type="text/css">* {
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
}
#page:left {
size: A4 landscape;
}
#page:right {
size: A4 portrait;
}
.page-portrait {
page-break-after: always;
}
.page-landscapes {
page-break-after: always;
}
</style>
</head>
<body>
<div class="page-portrait">
<p>This should be a portrait page</p>
</div>
<div class="page-landscapes">
<p>This should be a landscape page</p>
</div>
<div class="page-portrait">
<p>This should be a portrait page</p>
</div>
<div class="page-landscapes">
<p>This should be a landscape page</p>
</div>
</body>
</html>
Custom element processing with intermediate conversion to elements
You can utilize HtmlConverter.convertToElements to get intermediate element list and process them one by one, changing default page sizes as needed. Note that it will only work if the elements which break to the new pages are top-level elements in your HTML.
I will base my answer on the following HTML:
<html>
<head>
<title>UnitTest</title>
<style type="text/css">* {
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
}
.page-portrait {
page-break-after: always;
page: page-portrait;
}
.page-landscapes {
page-break-after: always;
page: page-landscape;
}
</style>
</head>
<body>
<div class="page-landscapes">
<p>This should be a portrait page</p>
</div>
<div class="page-portrait">
<p>This should be a landscape page</p>
</div>
<div class="page-landscapes">
<p>This should be a portrait page</p>
</div>
<div>
<p>This should be a landscape page</p>
</div>
</body>
</html>
First off, let's define a custom tag worker factory that is going to assign custom tag workers to <div> elements, the elements which can contain our special classes responsible for page breaks, as well as the tag worker for <div> elements itself which will be responsible for propagating our special classes to the resultant layout level elements:
private static class CustomDivTagWorker extends DivTagWorker {
public CustomDivTagWorker(IElementNode element, ProcessorContext context) {
super(element, context);
}
#Override
public void processEnd(IElementNode element, ProcessorContext context) {
super.processEnd(element, context);
IPropertyContainer result = getElementResult();
if (result != null) {
if ("page-portrait".equals(element.getAttribute("class"))) {
result.setProperty(PAGE_BREAK_AFTER_RPOPERTY, "portrait");
} else if ("page-landscapes".equals(element.getAttribute("class"))) {
result.setProperty(PAGE_BREAK_AFTER_RPOPERTY, "landscape");
}
}
}
}
private static class CustomTagWorkerFactory extends DefaultTagWorkerFactory {
#Override
public ITagWorker getCustomTagWorker(IElementNode tag, ProcessorContext context) {
if ("div".equals(tag.name())) {
return new CustomDivTagWorker(tag, context);
}
return super.getCustomTagWorker(tag, context);
}
}
Now the main code converts the HTML to elements, adds root elements one by one to the resultant Document (from layout module), and then processes presence of the special classes by changing the page size accordingly. Full code:
PdfDocument pdfDocument = new PdfDocument(new PdfWriter("path/to/out.pdf"));
ConverterProperties properties = new ConverterProperties();
properties.setTagWorkerFactory(new CustomTagWorkerFactory());
List<IElement> elements = HtmlConverter.convertToElements(new FileInputStream(sourceHTML), properties);
Document document = new Document(pdfDocument);
for (IElement element : elements) {
if (element instanceof IBlockElement) {
document.add((IBlockElement) element);
} else if (element instanceof AreaBreak) {
document.add((AreaBreak) element);
} else {
throw new RuntimeException();
}
if (element.hasProperty(PAGE_BREAK_AFTER_RPOPERTY)) {
String prop = element.getProperty(PAGE_BREAK_AFTER_RPOPERTY);
if ("portrait".equals(prop)) {
document.getPdfDocument().setDefaultPageSize(PageSize.A4);
} else {
document.getPdfDocument().setDefaultPageSize(PageSize.A4.rotate());
}
}
}
pdfDocument.close();

The best solution we have managed to find until now is the following, it works based on DIV level CSS class assignment to control the page orientation. It can be extended to work for other HTML tags and/or CSS classes.
The solution is designed to notify a page listener with the right orientation to apply, and rotating the page as needed. The tag worker inspects the HTML and looks for specific CSS classes to signal the page listener with the orientation found.
The benefit of this approach is that it allows to keep things 'simple' and use the 'HtmlConverter.convertToPdf' method which avoids lossing certain features baked into the underlying implementation.
PageOrientationsEventHandler eventHandler = new PageOrientationsEventHandler();
pdfDocument.addEventHandler(PdfDocumentEvent.START_PAGE, eventHandler);
converterProperties.setTagWorkerFactory(
new DefaultTagWorkerFactory() {
#Override
public ITagWorker getCustomTagWorker(IElementNode tag, ProcessorContext context) {
if (HTML_DIV.equalsIgnoreCase(tag.name())) {
return new CustomDivTagWorker(tag, context, pdfDocument, eventHandler);
}
return null;
}
});
// Run the conversion
HtmlConverter.convertToPdf(fis, pdfDocument, converterProperties);
And following referenced constants:
private static final String CSS_PAGE_PORTRAIT = "page";
private static final String CSS_PAGE_LANDSCAPE = "page-landscape";
And following referenced classes:
private static final class PageOrientationsEventHandler implements IEventHandler {
public static final PdfNumber PORTRAIT = new PdfNumber(0);
public static final PdfNumber LANDSCAPE = new PdfNumber(90);
private PdfNumber orientation = PORTRAIT;
private Map<Integer, PdfNumber> orientationHistory = new HashMap<Integer, PdfNumber>();
public void setOrientation(PdfNumber orientation) {
this.orientation = orientation;
}
#Override
public void handleEvent(Event currentEvent) {
PdfDocumentEvent docEvent = (PdfDocumentEvent) currentEvent;
PdfPage page = docEvent.getPage();
// Check if we already rendered this page before
int pageNr = docEvent.getDocument().getPageNumber(page);
if(orientationHistory.containsKey(pageNr)) {
// We did, use the same orientation
// as we re-render we have lost track of the right orientation instrucrion
// since it only works well on 1st pass, not on subsequent renders
orientation = orientationHistory.get(pageNr);
} else {
// First render pass, store orientation
orientationHistory.put(pageNr, orientation);
}
// Toggle orientation
page.setIgnorePageRotationForContent(LANDSCAPE.equals(orientation));
page.put(PdfName.Rotate, orientation);
}
}
private static final class CustomDivTagWorker extends DivTagWorker {
private IElementNode element;
private PageOrientationsEventHandler eventHandler;
public CustomDivTagWorker(IElementNode element, ProcessorContext context, PdfDocument pdfDocument, PageOrientationsEventHandler eventHandler) {
super(element, context);
this.element = element;
this.eventHandler = eventHandler;
}
#Override
public IPropertyContainer getElementResult() {
IPropertyContainer baseElementResult = super.getElementResult();
// We are interested in Divs only
if (baseElementResult instanceof Div) {
// Check landscape based on class identifier
boolean landscape = false;
String cssClass = element.getAttribute(AttributeConstants.CLASS);
if (CSS_PAGE_LANDSCAPE.equals(cssClass)) {
landscape=true;
} else if (CSS_PAGE_PORTRAIT.equals(cssClass)) {
landscape=false;
}
// Flag requested orientation to our start page handler
if(cssClass!=null && cssClass.length()>0) {
eventHandler.setOrientation(landscape?PageOrientationsEventHandler.LANDSCAPE:PageOrientationsEventHandler.PORTRAIT);
}
}
return baseElementResult;
}
}

Related

Returning object details in the View based on the object ID ASP.net core MVC

I'm building online catalog for phones, I have two controller one for phone Catalog and second for phone's details.With catalog everything is fine, now my goal is to see phone details after clicking on the phone's name or photo in the catalog.I think that with phone's id, its easier to solve this task, also I use repository pattern.
This Catalog' s Controller:
public class PhonesCatalog : Controller
{
private readonly IPhoneRepository _repository;
public int PageSize = 6;
public PhonesCatalog(IPhoneRepository repository)
{
_repository = repository;
}
[HttpGet]
public IActionResult Catalog(int productPage = 1)
=> View(new ProductsListViewModel
{
Phones = _repository.Phones
.OrderBy(x => x.PhoneId)
.Skip((productPage -1) * PageSize)
.Take(PageSize),
PagingInfo = new PagingInfo
{
CurrentPage = productPage,
ItemsPrePage = PageSize,
TotalItems = _repository.Phones.Count()
}
});
}
The repository pattern:
public interface IPhoneRepository
{
IQueryable<Phone> Phones { get; }
Phone GetPhoneById(int id);
}
public class EfMobileStoreRepository : IPhoneRepository
{
private readonly MobileStoreCatalogContext _context;
public EfMobileStoreRepository(MobileStoreCatalogContext context)
{
_context = context;
}
public IQueryable<Phone> Phones => _context.Phones;
public Phone GetPhoneById(int id) => _context.Phones
.FirstOrDefault(p => p.PhoneId == id);
}
and here is Phone detail controller and view:
public class PhonesDetails : Controller
{
private readonly IPhoneRepository _repository;
public PhonesDetails(IPhoneRepository repository)
{
_repository = repository;
}
[HttpGet]
public IActionResult Details(int id)
{
return View(_repository.GetPhoneById(id));
}
}
#model Mobile_Store_Catalog_wandio.Models.Phone
<h4>Phone Details</h4>
<div class="row">
<p>#Model.PhoneName</p>
<p>#Model.Manufactor</p>
<p>#Model.OperationSystem</p>
<p>#Model.Processor</p>
<p>#Model.Memory</p>
<p>#Model.ScreenResolution</p>
<p>#Model.Size</p>
<p>#Model.Wight</p>
</div>
Here Catalog View:
#model ProductsListViewModel
<h1>Phone Catalog</h1>
<div class="container-fluid">
<div class="container-fluid">
<div class="row">
<div class="col-md-3 btn-group-vertical text-center">
Filter
Search
</div>
<div class=" row col-md-9">
#foreach (var p in Model.Phones)
{
<div class=" col-md-4 border border-dark">
<a href="#Url.Action("Details", "PhonesDetails")">
<img class="img-fluid" src="/Images/#p.ImageName"/>
</a>
<p class="text-center container">#p.PhoneName</p>
<p class="text-white text-center bg-success">#p.Price.ToString("C2")</p>
</div>
}
</div>
</div>
</div>
</div>
<div class="row">
<div page-model="#Model.PagingInfo" page-action="Catalog" page-classes-enabled="true"
page-class="btn" page-class-normal="btn-outline-dark"
page-class-selected="btn-primary" class="btn-group-toggle m-1 al">
</div>
</div>
and here is the ProductViewList code:
public class ProductsListViewModel
{
public IEnumerable<Phone> Phones { get; set; }
public PagingInfo PagingInfo { get; set; }
}
Problem is that when I'm clicking on the phone image,but it takes only first id of phone and returns its detail,it doesn't matter which image is clicked, but I need to return details by id, not only first id Phone detail.
What I'm doing wrong here, can anyone help me?
You can change your code like this:
<a asp-controller="PhonesDetails" asp-action="Details" asp-route-id="#p.Id">
<img class="img-fluid" src="/Images/#p.ImageName"/></a>

Event of StatelessLinks in WebMarkupContainer don't fire

I have a form with a StatelessLink ("Delete profile?"). When this link is clicked a WebMarkupContainer is made visible containing two more links ("Really delete profile!" and "Cancel").
Java:
private StatelessLink deleteProfileWarningLink;
private WebMarkupContainer deleteProfileContainer;
private StatelessLink deleteProfileLink;
private StatelessLink deleteProfileCancelLink;
public MyForm() {
...
deleteProfileWarningLink = new StatelessLink("profileDeleteWarningLink") {
#Override
public void onClick() {
deleteProfileWarning();
}
};
deleteProfileContainer = new WebMarkupContainer("deleteProfileContainer");
deleteProfileContainer.setVisible(false);
deleteProfileLink = new StatelessLink("reallyDeleteProfileLink") {
#Override
public void onClick() {
deleteProfile();
}
};
deleteProfileCancelLink = new StatelessLink("cancelDeleteProfileLink") {
#Override
public void onClick() {
cancelDeleteProfile();
}
};
...
add(deleteProfileWarningLink);
deleteProfileContainer.add(deleteProfileLink);
deleteProfileContainer.add(deleteProfileCancelLink);
add(deleteProfileContainer);
}
And some HTML:
<fieldset>
<div wicket:id="deleteProfileContainer" class="deleteProfil">
<div class="wrapper">
<a wicket:id="reallyDeleteProfileLink" class="button delete">Really delete profile!</a>
<a wicket:id="cancelDeleteProfileLink" class="button cancel">Cancel</a>
</div>
</div>
<span class="unitA">
<a wicket:id="profileDeleteWarningLink" class="button delete">Delete profile?</a>
</span>
</fieldset>
However the events of the StatelessLinks in the WebMarkupContainer never fire.
I think you should optimize this with some custom JavaScript.
The idea is the following: Wicket generates all three buttons in the initial version of the page. The first button is initially visible and uses JavaScript to show the initially hidden (CSS, display:none) container with the other two buttons. The rest is as it is now.
Recently we discussed something related to your problem in dev# mailing list:
http://markmail.org/message/dkmxw4urqm444ryc

how to get current page in wicket

i am trying to create dynamic navigation links in which current page link should be highlighted but i am unable to get desired outcome. i am using listview to display my menu items but unable to highlight the current page link.
please suggest necessary changes
public class SearchPage extends WebPage implements Serializable {
private static final long serialVersionUID = 1L;
Logger log = Logger.getLogger(SearchPage.class);
public SearchPage() {
List<HeaderListItems> headerPOJOItems = new ArrayList<HeaderListItems>();
HeaderListItems searchHLI = new HeaderListItems();
searchHLI.setLabel("Search");
searchHLI.setDestPage(SearchPage.class);
headerPOJOItems.add(searchHLI);
HeaderListItems jobsHLI = new HeaderListItems();
jobsHLI.setLabel("Jobs");
jobsHLI.setDestPage(Jobs.class);
headerPOJOItems.add(jobsHLI);
HeaderListItems urlHLI = new HeaderListItems();
urlHLI.setLabel("URL");
urlHLI.setDestPage(URL.class);
headerPOJOItems.add(urlHLI);
HeaderListItems syssettingsHLI = new HeaderListItems();
syssettingsHLI.setLabel("System Settings");
syssettingsHLI.setDestPage(Settings.class);
headerPOJOItems.add(syssettingsHLI);
HeaderListItems usersHLI = new HeaderListItems();
usersHLI.setLabel("Users");
usersHLI.setDestPage(User.class);
headerPOJOItems.add(usersHLI);
HeaderListItems logoutHLI = new HeaderListItems();
logoutHLI.setLabel("Logout");
logoutHLI.setDestPage(WebApp.get().getHomePage());
headerPOJOItems.add(logoutHLI);
add(new ListView("headerlistview", headerPOJOItems) {
#Override
protected void populateItem(ListItem item) {
final HeaderListItems headerlistitems = (HeaderListItems) item
.getModelObject();
log.info("Label: " + headerlistitems.getLabel() + " dest: "
+ headerlistitems.getDestPage());
Link newlink = new Link("newlink") {
#Override
public void onClick() {
setResponsePage(headerlistitems.getDestPage());
}
};
newlink.add(new Label("newlabel", headerlistitems.getLabel()));
newlink.add(new AttributeModifier("class",
new AbstractReadOnlyModel() {
#Override
public Object getObject() {
// TODO Auto-generated method stub
return getPage().getClass().equals(
headerlistitems.getDestPage()
.getClass()) ? "activeitem"
: AttributeModifier.VALUELESS_ATTRIBUTE_REMOVE;
}
}));
item.add(newlink);
}
});
}
List is list of pojo item. my pojo has two fields label(String) and destPage(Class)
My Mark-up:
<html xmlns:wicket="http://wicket.apache.org">
<head>
<title>Search Page</title>
<link href="css/design.css" type="text/css" rel="stylesheet" />
</head>
<body>
<div id="container">
<div class="header">
<div class="header_tab1">
<p align="center">Logo</p>
</div>
<div class="header_tab2"> </div>
<div class="header_tab3">
<table width="100%">
<tr>
<td wicket:id="headerlistview">
<ul>
<li><a href="#" wicket:id="newlink"><span
wicket:id="newlabel"></span></a></li>
</ul>
</td>
</tr>
</table>
</div>
</div>
</div>
</body>
</html>
I have a CSS class activeitem which i am using in attribute modifier
Thanks in advance
Change the class comparison to:
return getPage().getClass().equals(
headerlistitems.getDestPage()) ? "activeitem" : AttributeModifier.VALUELESS_ATTRIBUTE_REMOVE;
The next step would be to extract the navigation into its own panel, so you can reuse it in your pages.
Good luck.

Sakai Site page tools alignment

i want to customize sakai site tool configuration like this format using layouts. but by default in sakai layout is possible by double layout or single layout. actually i need combination of both first row is double column layout and remaining single column layouts.
please tell me is there any option to do like this.or provide me guidance how to customize .here i am inserted image i want tool alignment like this
Thanks In Advance
http://i.stack.imgur.com/Xjy17.png
finally its working i did this. Please provide any suggestions if required for more flexibility or any other way to do this.
Kernel
Sitepage.java :-
Add
public static final int LAYOUT_MY_CUSTOM = 2;
BaseSitepage.java:-
Change this in
protected BaseSitePage(BaseSiteService siteService, Site site, String id, String title, String layout,
boolean popup)
{}
if (layout.equals(String.valueOf(LAYOUT_SINGLE_COL)))
{
m_layout = LAYOUT_SINGLE_COL;
}
else if (layout.equals(String.valueOf(LAYOUT_DOUBLE_COL)))
{
m_layout = LAYOUT_DOUBLE_COL;
}
else if(layout.equals(String.valueOf(LAYOUT_MY_CUSTOM))){
m_layout = LAYOUT_MY_CUSTOM;
}
And
protected BaseSitePage(BaseSiteService siteService, Site site, String id, String title, String layout,
boolean popup)
{} method
else if(layout.equals(String.valueOf(LAYOUT_MY_CUSTOM))){
m_layout = LAYOUT_MY_CUSTOM;
}
And
public void setLayout(int layout)
{
if ((layout == LAYOUT_SINGLE_COL) || (layout == LAYOUT_DOUBLE_COL) || (layout == LAYOUT_MY_CUSTOM))
{
m_layout = layout;
}
else
M_log.warn("setLayout(): set to invalid value: " + layout);
}
BaseSiteService.java:-
public String[] getLayoutNames()
{
String[] rv = new String[3];
rv[0] = rb.getString("sitpag.lay_sngl");
rv[1] = rb.getString("sitpag.lay_dbl");
rv[2] = rb.getString("sitpag.lay_cust1");
return rv; }
Portal:-
Comment following code in the method
public void includePage(PortalRenderContext rcontext, HttpServletResponse res,
HttpServletRequest req, Session session, SitePage page,
String toolContextPath, String wrapperClass) throws IOException
{
rcontext.put("pageColumnLayout", (page.getLayout()==SitePage.LAYOUT_DOUBLE_COL) ? "col1of2": "col1");
and replace the code
if(page.getLayout() == SitePage.LAYOUT_DOUBLE_COL){
rcontext.put("pageColumnLayout","col1of2");
}
else if(page.getLayout() == SitePage.LAYOUT_MY_CUSTOM){
rcontext.put("pageColumnLayout","SingleDouble");
}
else{
rcontext.put("pageColumnLayout","col1");
}
And change
rcontext.put("pageTwoColumn", Boolean
.valueOf(page.getLayout() == SitePage.LAYOUT_DOUBLE_COL || page.getLayout() == SitePage.LAYOUT_MY_CUSTOM));
And
// do the second column if needed
if (page.getLayout() == SitePage.LAYOUT_DOUBLE_COL ||page.getLayout() == SitePage.LAYOUT_MY_CUSTOM)
Site Manage:-
SiteAction.java
Add custom layout to following method 8990 line
private void addSynopticTool(SitePage page, String toolId,
String toolTitle, String layoutHint) {
if (page.getContainingSite() != null) {
if (page.getLayout() != SitePage.LAYOUT_SINGLE_COL || page.getLayout() != SitePage.LAYOUT_MY_CUSTOM|| !page.getContainingSite().isCustomPageOrdered() ) {
page.setLayout(SitePage.LAYOUT_DOUBLE_COL);
}
}
}
OSP Tool
XSltcharon portal:-
XsltrenderContext.java:-
Comment the following
/*pageElement.setAttribute("layout", (context.get("pageColumnLayout")
.equals("col1")) ? "0" : "1");*/
And replace with
String selectedLayout="0";
//context.put("pageColumnLayout","SingleDouble");
if(context.get("pageColumnLayout").equals("col1of2")){
selectedLayout="1";
}
else if(context.get("pageColumnLayout").equals("SingleDouble")){
selectedLayout="2";
}
else{
selectedLayout="0";
}
And add following statements in if (selected)
if(context.get("pageColumnLayout").equals("SingleDouble")){
Element column3 = doc.createElement("column");
Element column4 = doc.createElement("column");
Element column5 = doc.createElement("column");
column3.setAttribute("index","3");
column4.setAttribute("index","4");
column5.setAttribute("index","5");
LinkedList l1=new LinkedList();
LinkedList l2=new LinkedList();
LinkedList all=new LinkedList();
List column0Tools=(List)context.get("pageColumn0Tools");
List column1Tools=(List)context.get("pageColumn1Tools");
if(column0Tools !=null){
l1.add(column0Tools.get(0));
column3.appendChild(createColumnToolsXml(doc,l1, page));
column0Tools.remove(0);
if(column0Tools !=null)
{
all.addAll(column0Tools);
}
columns.appendChild(column3);
if(column1Tools !=null && column1Tools.size()>0 )
{ l2.add(column1Tools.get(0)); column4.appendChild(createColumnToolsXml(doc,l2, page));
column1Tools.remove(0);
if(column1Tools !=null){
all.addAll(column1Tools);
}
}
columns.appendChild(column4);
if(all !=null){
column5.appendChild(createColumnToolsXml(doc,all, page));
}
columns.appendChild(column5);
}
Osp-Portal
osp-portal.xsl:-
Add the following into portal.xslt and osp-portal.xsl
<!--
===============match single and Double============
process a selected page with two column layouts
param:content - "true" or "false" if rendering tool content or tool list
=========================================================
-->
<xsl:template match="page[#layout='2' and #selected='true']">
<xsl:param name="content"/>
<xsl:if test="$content='true'">
<xsl:call-template name="page-content-custom">
<xsl:with-param name="page" select="."/>
</xsl:call-template>
</xsl:if>
<xsl:if test="$content='false'">
<li>
<a accesskey="1" class="selected" href="#">
<xsl:attribute name="accesskey">
<xsl:value-of select="../../#order"/>
</xsl:attribute>
<xsl:value-of select="title"/>
</a>
</li>
</xsl:if>
</xsl:template>
<!--Custom Sarath -->
<xsl:template name="page-content-custom">
<xsl:param name="page" />
<h1 class="skip">
<xsl:value-of select="$externalized/entry[#key='sit.contentshead']" />
</h1>
<a id="tocontent" class="skip" name="tocontent"></a>
<div id="content">
<div id="col1of2">
<div class="portlet">
<p class="pageId">$page</p>
<xsl:for-each select="$page/columns/column[#index='3']/tools/tool">
<xsl:call-template name="tool">
<xsl:with-param name="tool" select="." />
</xsl:call-template>
</xsl:for-each>
</div>
</div>
<div id="col2of2">
<div class="portlet">
<xsl:for-each select="$page/columns/column[#index='4']/tools/tool">
<xsl:call-template name="tool">
<xsl:with-param name="tool" select="." />
</xsl:call-template>
</xsl:for-each>
</div>
</div>
<div id="col1">
<div class="portlet">
<xsl:for-each select="$page/columns/column[#index='5']/tools/tool">
<xsl:call-template name="tool">
<xsl:with-param name="tool" select="." />
</xsl:call-template>
</xsl:for-each>
</div>
</div>
</div>
</xsl:template>
in Portal.css file
#col1_new{
padding-right: .0em;
clear:both;
}
#col1of2_new{
width: 51%;
*/width: 48%;
float: left;
margin: 0;
margin-left: 0.3em;
}
#col2of2_new{
width: 48%;
*/width: 48%;
float: right;
}

Problem with Image uploading to SQL

I have problem with uploading image to SQL database.
i have Methods Upload in controller Upload
dbData userDb = new dbData();
public ActionResult Upload()
{
return View();
}
[HttpPost]
public ActionResult Upload(HttpPostedFileWrapper file)
{
if (file.ContentLength > 0)
{
Stream fileStream = file.InputStream;
string fileName = Path.GetFileName(file.FileName);
int fileLength = file.ContentLength;
byte[] fileData = new byte[fileLength];
fileStream.Read(fileData, 0, fileLength);
var image = new ImageTable();
image.Image = fileData;
image.Description = "Default profile picture";
try
{
userDb.ImageTables.InsertOnSubmit(image);
userDb.SubmitChanges();
return RedirectToAction("Success");
}
catch (Exception ex)
{
throw;
}
}
return View();
}
If i use this view page
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Upload</title>
</head>
<body>
<div>
<% using (Html.BeginForm("Upload", "Upload", FormMethod.Post, new { enctype = "multipart/form-data" }))
{%>
<input name="file" type="file" runat="server" id="file"/><br />
<input type="submit" value="Upload File" />
<%} %>
</div>
</body>
</html>
everithing works great but if i want to use view runned on masterpage i wil get this error after i click upload submit button:
No parameterless constructor defined for this object.
Know someone where is problem and how can i fix it ?
Thanks
This error occurs because default model binder can't create instances of classes that don't contain parameterless constructor (such as HttpPostedFileWrapper).
Simplest way around this is to just pull files from Request.Files (e.g. Request.Files["file"]).
Alternatively, you could create custom model binder for that.
UPDATE:
This is action method I used:
[HttpPost]
public ActionResult Index(FormCollection form)
{
var file = Request.Files["file"];
if(file != null && file.ContentLength > 0)
{
// ...
}
return View();
}