Как сохранить наполовину заполненную форму - PullRequest
5 голосов
/ 02 августа 2009

Я работаю над проектом, в котором мы хотели бы дать пользователю возможность сохранить свою частично заполненную форму, чтобы он мог вернуться позже и заполнить ее. Я пытаюсь понять, как именно я хочу это сделать. Сохраняю ли я их в одном пуле с заполненными приложениями, только с особым статусом? Я действительно не хочу жертвовать целостностью завершенных приложений, заставляя поля обнуляться, когда я не хочу, чтобы они были.

Должен ли я создать ту же структуру базы данных в другой схеме для хранения незавершенных приложений? Я мог бы заставить эту другую схему быть более слабой по отношению к ограничениям базы данных и пустым полям для учета неполных приложений.

Есть ли более простой способ сделать это? Есть ли способ, которым я могу просто сохранить состояние представления и восстановить его позже?

Спасибо за любой совет!

Ответы [ 5 ]

4 голосов
/ 02 августа 2009

Я боролся с той же проблемой. Одно из отличий заключается в том, что мой метод включает автоматическое сохранение Ajax, аналогичное тому, что вы видите в Gmail и Blogger. Но это не должно изменить реализацию, на самом деле.

Беда в том, что я не хотел сохранять в обычные таблицы, потому что это потребовало бы проверки (проверка целых чисел, валют, дат и т. Д.). И я не хотел раздражать пользователей об этом, когда они действительно просто пытаются уйти.

Я наконец-то придумал таблицу AjaxSavedData. Это постоянная таблица в базе данных, но содержащиеся в ней данные имеют тенденцию быть временными. Другими словами, он будет временно хранить данные пользователя, пока они фактически не завершат страницу и не перейдут на следующую.

Таблица состоит из нескольких столбцов:

AjaxSavedDataID - int:

Первичный ключ.

ИД пользователя - int:

Определить пользователя (достаточно просто).

PageName - varchar (100):

Необходимо, если вы работаете с несколькими страницами.

ControlID - varchar (100):

Я называю это ControlID, но на самом деле это просто свойство ClientID, которое .NET предоставляет для всех элементов WebControls. Так, если, например, txtEmail находится внутри пользовательского элемента управления с именем Contact, тогда ClientID будет Contact_txtEmail.

Значение - varchar (MAX):

Значение, введенное пользователем для данного поля или элемента управления.

DateChanged - datetime:

Дата добавления или изменения значения.

Наряду с некоторыми пользовательскими элементами управления, эта система позволяет легко "просто работать". На нашем сайте ClientID каждого текстового поля, выпадающего списка, списка радиобутонирования и т. Д. Гарантированно будет уникальным и непротиворечивым для данной страницы. Таким образом, я смог написать все это так, чтобы поиск сохраненных данных работал автоматически. Другими словами, мне не нужно подключать эту функцию каждый раз, когда я добавляю некоторые поля в форму.

Эта функция автоматического сохранения перейдет в очень динамичное приложение для онлайн-страхования бизнеса на techinsurance.com, чтобы сделать его немного более удобным для пользователя.

Если вам интересно, вот Javascript, который позволяет автоматически сохранять:

function getNewHTTPObject() {
    var xmlhttp;

    /** Special IE only code */
    /*@cc_on
    @if (@_jscript_version >= 5)
    try {
        xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
    }
    catch (e) {
        try {
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
        catch (E) {
            xmlhttp = false;
        }
    }
    @else
        xmlhttp = false;
    @end
    @*/

    /** Every other browser on the planet */
    if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
        try {
            xmlhttp = new XMLHttpRequest();
        }
        catch (e) {
            xmlhttp = false;
        }
    }

    return xmlhttp;
}

function AjaxSend(url, myfunction) {
    var xmlHttp = getNewHTTPObject();
    url = url + "&_did=" + Date();
    xmlHttp.open("GET", url, true);
    var requestTimer = setTimeout(function() { xmlHttp.abort(); }, 2000);
    xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    xmlHttp.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2005 00:00:00 GMT");
    xmlHttp.onreadystatechange = function() {
        if (xmlHttp.readyState != 4)
            return;
        var result = xmlHttp.responseText;
        myfunction(result);
    };
    xmlHttp.send(null);
}

// Autosave functions
var SaveQueue = []; // contains id's to the DOM object where the value can be found
var SaveQueueID = []; // contains id's for binding references (not always the same)

function ArrayContains(arr, value) {
    for (i = 0; i < arr.length; i++) {
        if (arr[i] == value)
            return true;
    }

    return false;
}

function GetShortTime() {
    var a_p = "";
    var d = new Date();
    var curr_hour = d.getHours();

    if (curr_hour < 12)
        a_p = "AM";
    else
        a_p = "PM";

    if (curr_hour == 0)
        curr_hour = 12;
    else if (curr_hour > 12)
        curr_hour = curr_hour - 12;

    var curr_min = d.getMinutes();
    curr_min = curr_min + "";

    if (curr_min.length == 1)
        curr_min = "0" + curr_min;

    return curr_hour + ":" + curr_min + " " + a_p;
}

function Saved(result) {
    if (result == "OK") {
        document.getElementById("divAutoSaved").innerHTML = "Application auto-saved at " + GetShortTime();
        document.getElementById("divAutoSaved").style.display = "";
    }
    else {
        document.getElementById("divAutoSaved").innerHTML = result;
        document.getElementById("divAutoSaved").style.display = "";
    }
}

function getQueryString(name, defaultValue) {
    var query = window.location.search.substring(1);
    var vars = query.split("&");
    for (var i = 0; i < vars.length; i++) {
        var pair = vars[i].split("=");
        if (pair[0] == name) {
            return pair[1];
        }
    }

    return defaultValue;
}

function urlencode(str) {
    return escape(str).replace(/\+/g, '%2B').replace(/%20/g, '+').replace(/\*/g, '%2A').replace(/\//g, '%2F').replace(/@/g, '%40');
}

function AutoSave() {
    if (SaveQueue.length > 0) {
        var url = "/AjaxAutoSave.aspx?step=" + getQueryString("step", "ContactInformation");

        for (i = 0; i < SaveQueue.length; i++) {
            switch (document.getElementById(SaveQueue[i]).type) {
                case "radio":
                    if (document.getElementById(SaveQueue[i]).checked)
                        url += "&" + SaveQueueID[i] + "=" + urlencode(document.getElementById(SaveQueue[i]).value);
                    break;
                case "checkbox":
                    if (document.getElementById(SaveQueue[i]).checked)
                        url += "&" + SaveQueueID[i] + "=" + urlencode(document.getElementById(SaveQueue[i]).value);
                default:
                    url += "&" + SaveQueueID[i] + "=" + urlencode(document.getElementById(SaveQueue[i]).value);
            }
        }

        SaveQueue = [];
        SaveQueueID = [];
        AjaxSend(url, Saved);
    }
}

function AddToQueue(elem, id) {
    if (id == null || id.length == 0)
        id = elem.id;

    if (!ArrayContains(SaveQueueID, id)) {
        SaveQueue[SaveQueue.length] = elem.id;
        SaveQueueID[SaveQueueID.length] = id;
    }
}

Добавьте это на свою страницу, чтобы сделать эту работу:

window.setInterval("AutoSave()", 5000);

И чтобы применить это к Textbox, DropdownList, Listbox или Checkbox, вам просто нужно добавить этот атрибут:

onchange="AddToQueue(this)"

... или это для RadioButtonList или CheckBoxList:

onchange="AddToQueue(this, '" + this.ClientID + "')"
3 голосов
/ 02 августа 2009

Очевидно, что вы не можете сохранить его в реальных таблицах данных, поэтому я бы создал отдельную таблицу с идентификатором пользователя, формидом и двоичным типом данных. Объединить формы в некоторую сериализуемую структуру и сериализовать в БД. Когда пользователь возвращается, вы можете десериализовать и восстановить состояние формы.

1 голос
/ 02 августа 2009

Может быть несколько различий между вашими заполненными приложениями и этими "половинными" состояниями:

  1. Как вы говорите, большинство проверок неуместно, поля будут нулевыми, перекрестная проверка, вероятно, не может быть выполнена.
  2. Возможно, вам не нужны произвольные возможности поиска по данным.

Поэтому я бы использовал другую базу данных, в которой запись содержала бы несколько ключевых полей, таких как идентификатор пользователя, дата, вид формы, которую они заполняют и т. Д., И blob полей они заполнились. Я парень по Java, поэтому я не знаю способ получения BLOB-объектов .NET, но в Java я мог бы сериализовать объекты данных, поддерживающие форму.

Кажется, что в C # методы имеют некоторое сходство с Java, по крайней мере, я правильно понимаю эту статью .

Я бы подумал, что создание вручную простого кода "saveAsAString" и "readFromString" было бы немного скучно, но вполне выполнимо, если бы не было стандартных методов .Net.

0 голосов
/ 03 августа 2009

Когда-нибудь задумывались об использовании Silverlight? Silverlight имеет изолированное хранилище, я видел несколько примеров, когда разработчики используют изолированное хранилище для хранения дорогих данных на стороне клиента.

http://pietschsoft.com/post/2008/10/Silverlight-Client-Side-Database-via-LINQ-and-Isolated-Storage.aspx

А затем с помощью js получить данные в out:

http://msdn.microsoft.com/en-us/library/cc221414%28VS.95%29.aspx

Это избавляет вас от необходимости в дополнительном пространстве БД, поскольку все временные записи формы пользователя хранятся в изолированном хранилище, когда они возвращаются на страницу, вы спрашиваете пользователя, хотят ли они возобновить редактирование ..., а затем заполняете форму с данными в изолированном хранилище ...

звучит более изящно, чем добавление новой базы данных?

Есть и обратная сторона, которая является машинно-зависимым решением.

Зависит от точной цели сохранения частичных форм? Это так, что его можно поднять на других машинах? Если это так, то это неправильное решение, и сохранение БД - лучшее зло.

0 голосов
/ 02 августа 2009

Я бы определенно сохранил его в базе данных. Ваш план сохранения с особым статусом (логический флаг с именем Complete будет работать). Затем вы можете создать представление, которое извлекает только те элементы, для которых Complete = true и называется CompletedApplications.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...