|
|
|
|
为什么我遇到异常"[MC01]no xsn ..."? |
InfoJet Service将注册的表单模板缓存到服务器内存中。
所以当AppDomain或IIS重启,已注册的表单模板将丢失,InfoJet Service在处理被丢失的表单模板时将抛出这个异常。
所以我们建议在调用下列方法前使用Publish Url检查表单模板是否存在于InfoJet Service中,如果不存在则重新注册它:
InfoJetService.BuildFormByTemplate(),
InfoJetService.BuildFormByXml(),
InfoJetService.ReloadForm() 和
InfoJetservice.UpdateForm(),
如下:
if( !InfoJetService.ContainsXSN( publishUrl ) )
{
//根据Publish Url重新加载表单模板内容。
//然后调用方法InfoJetService.Register()。
}
在xdoc.aspx.cs中,可以用下面的方法检查:
string publishUrl = this.Context.Request[ "xdoc_param_xsn_uri" ];
if( publishUrl != null && publishUrl.Length > 0 )
{
if( !InfoJetService.ContainsXSN( publishUrl ) )
{
//根据Publish Url重新加载表单模板内容。
//然后调用方法InfoJetService.Register()。
}
}
xdoc.aspx请求参数"xdoc_param_xsn_uri"的值是当前表单的Publish Url.
有很多原因可以导致AppDomain或IIS重新启动,请在全局Application_End()方法中使用System.Web.Hosting.HostingEnvironment.ShutdownReason属性来检查具体原因。
不合适的InfoJet Service配置也能导致AppDomain重新启动,请参考下列内容:
http://www.infojetsoft.com/service_config.htm#InlineFilePath
http://www.infojetsoft.com/service_config.htm#ResourceFilePath
http://www.infojetsoft.com/service_config.htm#TempFolder
另外,InfoJet Service也把辅助数据源存储在会话状态中,当AppDomain或IIS重新启动,In-process会话状态将丢失,使用辅助数据源的表单可能将不能正常工作,所以我们建议使用Out-of-process或SQL Server会话状态。
|
|
|
Postback时服务端异常如何处理? |
|
InfoJet Service在Postback开始和结束时将自动调用下列方法,所以可以在它们中禁用/启用保存按钮:
<script language="javascript">
function InfoJetCustom_OnPostbackStart(){
var saveButton = document.getElementById( "SaveButton" );
if( saveButton )
{
saveButton.disabled = true;
}
}
function InfoJetCustom_OnPostbackEnd(){
var saveButton = document.getElementById( "SaveButton" );
if( saveButton )
{
saveButton.disabled = false;
}
}
</script>
当Postback时,表单可能包含"脏"数据,所以我们建议禁用保存按钮来保持数据完整性。
|
|
|
Postback时服务端异常如何处理? |
|
我们建议用如下方式在web.config中指定一个自定义错误页面:
<customErrors mode="On" defaultRedirect="~/ErrorPage.aspx">
</customErrors>
(1). 使用AJAX Postback模式时,请在自定义错误页面中加入下列PostbackError指令:
<!--InfoJetSoft.Service.PostbackError-->
<!--InfoJetSoft.Service.ErrorMessage(详细出错信息)-->
InfoJet Service将调用InfoJet_OnPostbackError()方法来停止Postback并撤消用户上次输入。ErrorMessage指令用于给用户显示一个详细的出错信息。
(2). 使用非AJAX(隐藏的IFrame)Postback模式时,请在自定义错误页面中添加下列脚本:
<script language="javascript">
//自定义错误页面在iframe中显示。
if(self.location != top.location){
//父文档包含InfoJet Service Web表单。
if( parent != null && parent.document.getElementById( "xdoc" ) != null ){
parent.InfoJet_OnPostbackError("The detailed message here");
}
}
</script>
自定义错误页面也能够捕获脚本超时异常。
另外,我们建议使用AJAX Postback模式,因为AJAX模式提供了对网络传输的更多控制。例如,InfoJet Service可以在AJAX模式下探测到网络中端,并通过调用InfoJet_OnPostbackError()来自动恢复失败的Postback,但是非AJAX模式则不支持这个功能。
|
|
|
Postback时会话超时如何处理? |
1. 如果使用表单验证保护xdoc.aspx,Postback将被转发到登录页面。
(1). 使用AJAX Postback模式时,请在登录页面中加入下列Relogin指令:
<!--InfoJetSoft.Service.Relogin-->
InfoJet Service发现Relogin指令时将自动调用InfoJetCustom_ReloginAfterAJAXPostback()方法,请在表单编辑页面中实现它来处理页面转发:
<script language="javascript">
function InfoJetCustom_ReloginAfterAJAXPostback()
{
OnUserRelogin();
}
</script>
(2). 使用非AJAX(隐藏的IFrame)Postback模式时,请在登录页面中添加下列脚本:
<script language="javascript">
//check to see if page is inside iframe
if( self.location != top.location )
{
parent.OnUserRelogin();
}
</script>
2. 使用集成Windows验证或基于HTTP的验证保护xdoc.aspx时,或未保护xdoc.aspx时,请参考xdoc.aspx.cs中的下列代码:
|
|
|
当会话超时时如何恢复XML表单? |
|
当HTTP会话丢失且用户不需要重新登录时,我们可以将表单提交到一个页面来恢复表单数据,并重新打开它。
在HTTP会话丢失时,表单的会话数据同时丢失,所以我们建议重新打开表单。
请参考表单编辑页面中的下列代码:
<script language="javascript">
function OnFormReopen()
{
var reopenButton = document.getElementById('ReopenButton');
reopenButton.click();
}
</script>
<form>
<asp:Label ID="xDocView" runat="server" EnableViewState="False"/>
<asp:Button id="ReopenButton" PostBackUrl="~/Reopen.aspx" runat="server"
style="display:none;"/>
</form>
在Reopen.aspx.cs中:
string publishUrl = this.Context.Request["xdoc_param_xsn_uri"];
if (publishUrl != null && publishUrl.Length > 0)
{
if (!InfoJetService.ContainsXSN(publishUrl))
{
//Try to load the binary content of the form template by the publishUrl.
//Then please call InfoJetService.Register().
}
string xml = InfoJetService.RecoverNonDirtyFormXml(this.Context);
InfoJetForm form = InfoJetService.BuildFormByXML(this.Context, publishUrl, xml);
this.xDocView.Text = form.Xhtml;
}
这个方法用于从请求中恢复去除了"脏"数据的表单XML。
由字段change事件触发的Postback没有成功结束时,返回的XML中的字段值将是change事件前的原值,而不是字段的新值("脏"数据),因为相关的计算和规则可能没有被正确处理。
|
|
|
当重新登录时如何恢复XML表单? |
请参考 当错误发生时如何恢复XML表单? 。
当表单被提交到登录页面,我们可以将表单参数输出的验证表单中,以便在用户登录成功后恢复表单:
protected void Page_Load(object sender, EventArgs e)
{
foreach (string key in this.Context.Request.Params.AllKeys)
{
if (key.StartsWith("xdoc_"))
{
string keyValue = this.Context.Request.Params[key];
HtmlInputHidden hidden = new HtmlInputHidden();
hidden.ID = key;
hidden.Name = key;
hidden.Value = keyValue;
this.LoginForm.Controls.Add(hidden);
}
}
}
|
|
|
如果通过邮件提交表单? |
|
要启用邮件提交,配置键InfoJetSoft.Service.SmtpServer和InfoJetSoft.Service.MailFrom必须被设置。
InfoJet Service将使用SmtpServer上的MailFrom帐号发送邮件。
如果SMTP服务器需要认证,键InfoJetSoft.Service.MailUserName和InfoJetSoft.Service.MailPassword也必须被设置。
也需要InfoJetSoft.Service.TempFolder键,InfoJet Service将把邮件附件(XML文档)缓存在其中。
并请将TempFolder目录的"完全控制"权限赋予给运行InfoJet Service的帐户。
如果impersonation被启用,最好将"完全控制"权限赋予给everyone。
|
|
|
如何打印从InfoPath Web表单导出的MHT文件? |
|
可以使用下列按钮代码打印导出的MHT文件:
function CTRL23_5::OnClick(eventObj)
{
XDocument.View.Export( "test.mht", "MHT" );
if( Application.InfoJetService )
{
Application.RunClientCode( "var mhtWindow = window.open( window.location.protocol + '//' + window.location.host + '" + XDocument.View.ExportPath + "');" );
Application.RunClientCode( "mhtWindow.print();" );
Application.RunClientCodeOnly();
}
}
在导出的MHT文件中,按钮控件被隐藏,下拉框、单选、复选按钮将被转换为文本。
这个功能需要配置键"InfoJetSoft.Service.InlineFilePath",MHT文件将被导出到InlineFilePath。
另外,可以使用如下的位于InfoPath Web表单外部的HTML按钮来在新浏览器窗口中打开由当前表单视图导出的MHT文件(需要配置键"InfoJetSoft.Service.InlineFilePath"):
<input type="button" onclick="InfoJet_OpenPrintableVersion(this);" value="可打印版本">
|
|
|
如何清空InfoJet Service缓存在HTTP会话中的表单数据? |
|
InfoJet Service缓存的表单数据的Session键值存储在InfoPath Web表单(InfoJetForm.Xhtml)的HTML隐藏字段"xdoc_param_form_id"中。
所以,当你想清空当前表单使用的会话数据时,需要提交这个Session键值。
一般来说,有两种情况:
1. 用户提交表单保存,之后被重定向到其它页面。
Session键的值已经包含在表单中,所以你可以直接使用下面的代码:
InfoJetForm savedForm = InfoJetService.ReloadForm(Context);
InfoJetService.ClearFormCache(Context);
//重定向到其它页面。
2. 用户点击了一个"关闭"按钮直接关闭浏览器.
这种情况下,不需要提交整个表单,但是需要使用JavaScript提交"xdoc_param_form_id"到服务端。
var formId = document.getElementById("xdoc_param_form_id");
if( formId != null ){
document.location="ClearSession.aspx?xdoc_param_form_id="+formId.value;
}
在ClearSession.aspx中:
<html>
<% InfoJetService.ClearFormCache(Context) %>
<script language=javascript>window.opener=null; window.close();</script>
</html>
CleaFormCache()方法也会同时清除表单使用的临时文件。
当用户退出登录时,请调用下面的方法清空当前用户使用的HTTP会话数据和临时文件:
InfoJetService.ClearUserCache(Context);
InfoJet Service演示程序中包含了相关代码,请参考。
|
|
|
如何使用自定义图片链接函数? |
|
您需要重写infojet.js中的InfoJetCustom_OnLinkedPictureClick(event, linkedPicture)函数。
当用户点击链接图片时InfoJet Service会自动调用这个函数。
你需要在这个函数中设置linkedPicture的src属性,然后调用InfoJet_UpdateField(linkedPicture)。
|
|
|
如何连接到Oracle? |
要连接到Oracle,请先基于SQL Server数据库设计表单模板,然后在Oracle中创建同样结构的表。
再在web.config中添加下列配置键:
<add key="InfoJetSoft.Service.GlobalConnectionString" value="Provider=msdaora;Data Source=XE;User Id=hr;Password=hr;"/>
(目前,只支持OLEDB驱动。)
GlobalConnectionString键将替换表单模板中的所有数据库连接串。
|
|