我希望有人能帮助我。
我有一个基于Backbone的SPA,用于响应式网站,其中.net WebAPI提供所有数据。
我最近发现了一个奇怪的问题。我添加了一个搜索框,搜索系统中的一个目录。这适用于桌面浏览器和Android。在iOS上,执行搜索似乎会将您带回到登录页面。
您可以通过各种方式执行搜索,您可以按Enter键,也可以单击搜索图标。然后,这两个触发一个方法,将路由器导航到搜索结果的URL。
我的第一个想法是,这是一些按钮怪异,但我不认为这是问题,因为两种搜索执行方法都会导致同样的问题。
搜索结果显示在受保护的视图中(它需要存在用户名 - 它存储在页面上的隐藏字段中)。网站上有两个搜索框 - 一个在主页上,另一个在搜索结果页面上(当你第一次加载它时显示一个默认设置 - 它第一次加载时很好)。两个搜索框都表现出相同的行为。
我的网站设置方式是当Backbone撤回模型时,如果它从API返回401,那么它会将您发送回登录页面,所以我只能认为它是发生在这里。
这是我的观看代码......
function (SiansPlan, ErrorManager, RecipeSearchResult, Header, Components, TemplateSource) {
var recipeSearchView = SiansPlan.SecureView.extend({
name: 'Recipe Search',
sectionName: 'Recipes',
queryText: '',
template: Handlebars.compile(TemplateSource),
headerView: new Header({ text: 'Recipes', swatch: 'e' }),
searchBoxRegion: undefined,
$searchWrapper: undefined,
$queryHeaderMobile: undefined,
$queryHeaderDesktop: undefined,
$searchButton: undefined,
$searchInput: undefined,
$recipeSearch : undefined,
events: {
'click .link-container': 'showRecipe',
'click #searchWrapper': 'showSearch',
'click #searchButton': 'showOrPerformSearch',
'keydown #searchButton': 'performSearchOnEnter',
'keydown #recipeSearch': 'performSearchOnEnter'
},
initialize: function (options) {
this.options = options || {};
SiansPlan.SecureView.prototype.initialize.call(this, options);
this.queryText = Object.exists(this.options.query) ? this.options.query : '';
},
bindData: function () {
this.$el.html(this.template({ results: this.collection.toJSON() }));
},
render: function () {
var that = this;
if (this.isSecured()) {
this.trigger('rendering');
var params = {
success: function () {
that.bindData();
that.trigger('rendered');
},
error: function (model, xhr) {
if (Object.exists(xhr) && xhr.status == 401) {
that.applyTimedOutSecureLoginPrompt();
} else {
that.$el.html('Unable to fetch search results');
ErrorManager.handleXhr('Search failed', xhr);
}
that.trigger('rendered');
}
};
if (!Object.exists(this.collection)) {
this.collection = new RecipeSearchResult.Collection({ username: SiansPlanApp.session.username(), query: this.queryText });
}
this.collection.fetch(params);
} else {
this.applySecureLoginPrompt();
}
return this;
},
postRender: function () {
var that = this;
var queryHeader = "All recipes";
if (Object.hasValue(this.queryText)) {
queryHeader = this.collection.length + " results for '" + this.queryText + "'";
}
this.$searchWrapper = $('#searchWrapper');
this.$queryHeaderMobile = $('#queryHeaderMobile');
this.$queryHeaderDesktop = $('#queryHeaderDesktop');
this.$searchButton = $('#searchWrapper');
this.$searchInput = $('#searchInput');
this.$recipeSearch = $('#recipeSearch');
this.$queryHeaderMobile.html(queryHeader);
this.$queryHeaderDesktop.html(queryHeader);
this.$recipeSearch.val(this.queryText);
SiansPlanApp.session.waitForLoad(30, function () {
that.searchBoxRegion = new SiansPlan.Region({ el: '.recipe-search-box-container' });
that.searchBoxRegion.renderView(new Components.RecipeSearchBox({ username: SiansPlanApp.session.username(), query: that.queryText, title: 'Search' }));
});
},
performSearchOnEnter: function (e) {
if (e.keyCode == 13) {
this.showOrPerformSearch(e);
}
},
showOrPerformSearch: function (e) {
if (!this.$searchInput.is(':visible')) {
this.showSearch(e);
} else {
e.preventDefault();
var url = '/recipes/search/' + this.$recipeSearch.val();
window.SiansPlanApp.router.navigate(url, true);
}
return false;
},
showRecipe: function (e) {
e.preventDefault();
var url = $(e.target).find('a').first().attr('href');
window.SiansPlanApp.router.navigate(url, true);
},
showSearch: function (e) {
e.preventDefault();
if (!this.$searchInput.is(':visible')) {
this.$queryHeaderMobile.hide();
this.$searchInput.show();
this.$recipeSearch.focus();
this.$recipeSearch.select();
}
return false;
}
});
return recipeSearchView;
});
更新
我已在脚本中设置了一些警告,以查看正在进行的操作,并且我发现了以下内容......
render: function () {
var that = this;
if (this.isSecured()) {
this.trigger('rendering');
var params = {
success: function () {
alert('Bind has succeeded!');
that.bindData();
that.trigger('rendered');
},
error: function (model, xhr) {
alert('Bind has failed!');
if (Object.exists(xhr) && xhr.status == 401) {
that.applyTimedOutSecureLoginPrompt();
} else {
that.$el.html('Unable to fetch search results');
ErrorManager.handleXhr('Search failed', xhr);
}
that.trigger('rendered');
alert(xhr.status + ' ' + xhr.responseText);
}
};
if (!Object.exists(this.collection)) {
alert('Binding new collection: ' + SiansPlanApp.session.username() + ' - ' + this.queryText);
this.collection = new RecipeSearchResult.Collection({ username: SiansPlanApp.session.username(), query: this.queryText });
}
alert('About to fetch using ' + this.collection.url());
this.collection.fetch(params);
} else {
alert('I dont appear to be secured??');
this.applySecureLoginPrompt();
}
return this;
},
当我第一次加载页面(显示所有结果)时,它加载正常并且“成功结合!”#39;出现。 API调用是/ api / recipes / search / {username} /
当我提交搜索条件时,使用/ api / recipes / search / {username} / {query}的API调用失败(' Bind failed!')并返回401。
这让我比以前更加困惑,因为现在看起来像API问题,但其他设备工作正常,如果我向Fiddler提交相同的查询,一切都如预期的那样好。
答案 0 :(得分:0)
我在最小的地方找到了答案......
问题是搜索条件有一个大写字母。因此,例如,当使用'Fish'进行搜索时,API会生成301,其重定向到/ api / recipes / search / {username} / fish。 iOS不喜欢这样,并将其报告为401(真的很糟糕!)