Как одиночная отправка реализована в EPiServer Xforms?

Как реализована функция Один и тот же человек может отправить форму несколько раз? Когда это поле в редакторе XForm снято, пользователь может отправить форму только один раз.

Я думал, что для анонимных пользователей это было основано на файле cookie, но я не вижу никаких соответствующих файлов cookie, передаваемых по сети. Глядя на EPiServer.XForms.XFormData.HasAlreadyPosted(Page page) в ILSpy, видно, что на самом деле он проверяет файл cookie, если для параметров сохранения не установлено значение «База данных» или значение UserName равно null.

В этой ситуации он проверяет файл cookie с именем «FormCookie»:

private static bool CheckCookieForPostedForm(Guid formId, Page page)
{
    HttpCookie httpCookie = page.Request.Cookies["FormCookie"];
    if (httpCookie != null)
    {
        foreach (string text in httpCookie.Values.Keys)
        {
            if (text.Equals(formId.ToString()))
            {
                return true;
            }
        }
        return false;
    }
    return false;
}

Я тестирую как анонимный пользователь, но в запросе или ответе на POST формы или в запросе или ответе на странице «Спасибо» нет «FormCookie», поэтому я не вижу, как это работает.

Следуя логике для анонимных пользователей, если вы отправляете сообщение в базу данных и имя пользователя не равно нулю, существует запрос Linq, который проверяет DDS на наличие отправки с совпадающим идентификатором формы и именем пользователя.

public bool HasAlreadyPosted(Page page)
{
    if ((this.ChannelOptions & ChannelOptions.Database) != ChannelOptions.Database  
        || this.UserName == null)
    {
        return XFormData.CheckCookieForPostedForm(this.FormId, page);
    }

    if (Guid.Empty.Equals(this.FormId))
    {
        throw new InvalidOperationException(  
          "Cannot read the XFormData before the FormName property has been set");
    }

    DynamicDataStore store = XFormData.GetStore(this.FormId);
    int num = (from post in store.ItemsAsPropertyBag()
               where (Guid)post["Meta_FormId"] == this.FormId &&  
                     (string)post["Meta_UserName"] == this.UserName
               select post).Count<PropertyBag>();
    return num > 0;
}

Глядя в базу данных (tblXFormData), в столбце UserName нет значений NULL. Может ли быть так, что вышеприведенная проверка this.UserName == null завершается неудачей, а затем выполняется запрос Linq, который сравнивает имя пользователя анонимного пользователя с именами пользователей в таблице, из которых есть пустое имя от первого анонимного пользователя и сообщает о ложном срабатывании?


person Greg B    schedule 30.11.2011    source источник


Ответы (1)


Что мне удалось сделать, так это использовать в методе OnInit событие AfterSubmitPostedData, чтобы затем использовать метод SetPostedCookie в обработчике. Затем создается файл cookie FormCookie, как описано в вашем сообщении.

Документация по API не самая лучшая.

public void FormControl_AfterSubmitPostedData(object sender, SaveFormDataEventArgs e)
{
    this.ShowStats();

    // we do this in the case of an anonymous user votes on the site.
    XFormData xfd = this.FormControl.FormDefinition.CreateFormData();
    xfd.SetPostedCookie(xfd.FormId, Page);
}
person horls    schedule 29.05.2012