I would like to clarify how do ext 4 models correlate to form panels.
Suppose I have a model, e.g. "User", which has a REST proxy attached.
When I want to modify user parameters, i use form's
loadRecord( Ext.data.Model record ) : Ext.form.Basic
method, to set form's field values.
After modification, I call "updateRecord" method, to send changes from form to loaded model, and then use model's "save" method, to send changes to server. This works quite well, and seems to fit Ext MVC concepts.
Question
But, the question is: how should I conform to MVC, in case I need to upload file, while modifying user's data (e.g. avatar). According to what I learned from docs, I should switch to using form's "submit" method to send updated data so server, including the file.
In this case, I see several drawbacks:
The original model, loaded to the form, will not be updated.
If I update the model (using "updateRecord", or other way), the model will stay in dirty state, however, changes have already been sent to server.
The same proxy configuration should be applied to form, as to model, so that I would not need to change server side.
Is this a correct way of implementing file-upload through ext forms?
Is there any way to do this using model.save method, to be more MVC-stylish?
I don't think you can combine two thing together. File upload will always be something different than submitting the rest of the data. What you can do however:
Have a button to select and upload file to the server. But don't save file into the same place where you save your user (for example you can have separate file storage and save just file name into the user record)
When sending user record update to the server send new file name. This way your avatar update and other data update will be in the same transaction.
Related
I'm new to the concept of DDD and CQRS and can't find a final solution how to upload images, or files in general, in a clean way.
Imagine the following scenario:
In an online portal there is a support request formular where a file (image in specific) could be attached to.
The posted data will raise a CreateSupportRequestCommand. Then the required aggregates will be loaded and changed.
I have three ideas to solve this, but I'm not very satisfied with them.
Way 1:
1. Post all data including the image (multipart) in a single request
2. Create a FileUploadCommand, which is returning the FileUploadId.
3. After that create a CreateSupportRequestCommand and pass the FileUploadId with the root data in the constructor.
Drawback: A single request will trigger two commands. In terms of CQRS one user interaction should be only one command.
Way 2:
1. Post the image to a seperate endpoint, create a temporary file and return the id or a file handle.
2. Post the formular with the attached tempfile id.
3. Invoke the CreateSupportRequestCommand with all root data including a file handle which points to the physical file.
4. Inside the command persist the tempfile into a FileUpload aggregate (by FileUploadRepository) then
5. Create the SupportRequest aggregate, assign the FileUploadId and persist.
Drawback: I handle 2 aggregates in the same command. Creating a support request is not responsible for uploading the file.
Way 3:
1. Post the image to a seperate endpoint, create a temporary file and return the id or a file handle.
2. Post the formular with the attached tempfile id.
3. Invoke the CreateSupportRequestCommand with all root data including a file handle which points to the physical file.
4. Only persist the root data to the SupportRequest aggregate. Raise a SupportRequestCreatedEvent and attach the file handle.
5. Inside the event process and assign the file handle.
Drawback: The SupportRequestCreatedEvent should not really care about a file handle.
Is there a better way to solve this?
I do not think handling File upload is a Domain Concern. The file metadata like FileContentId may be part of your domain but not the actual file upload. I would perform the file operation before the CommandHandler is executed. Probably in a middleware or perhaps before queing up the Command onto the message bus.
CreateSupportRequestCommandHandler would then only be invoking an operation like CreateSupportRequest on your aggrerate (say SupportRequest). Within that CreateSupportRequest method you will have all your business rule pretaining to the operation. SupportRequest then eventually would be saved in your repository.
This is somewhat a duplicate of this question, but that question has no (valid) answer and is 1.5 years old so asking my own with hopes people have more info now.
If you are using multiple instances of a WebBrowser control, MSHTML, IHTMLDocument, or whatever... from inside the APP instance, mostly IInternetProtocol::Start, is there a way to know which instance is loading the resource? Or is there a way to use a different APP for each instance of the control, maybe by providing one via IDocHostUIHandler or ICustomDoc or otherwise? I'm currently using IInternetSession::RegisterNameSpace to make it process wide.
Optional reading below, don't feel you need to read it unless above isn't clear.
I'm working on a legacy (Win32 C++) email client that uses the MS ActiveX WebBrowser control (MSHTML or other names it goes by) to display HTML emails. It was saving everything to temp files, updating the cid: URLs, and then having the control load that. Now I want to do it the correct way, using APP. I've got it all working with some test code that just uses static variables/globals and loads one email.
My problem now is, the app might have several instances of the control all loading different emails (and other stuff) at the same time... not really multiple threads so much, just the asynchronous nature of the control. I can give each instance of the control a unique URL to load the email, say, cid:email-GUID, and then in my APP code I can use that URL to know which email to load. However, when it comes to loading any content inside the email, like attached images using src="cid:", those will not always be unique so I will not always know which image it is, for which email. I'd like to avoid having to modify the URLs of the HTML before displaying it (I'm doing that now for the temp file thing, but want to do it a better way).
IInternetBindInfo::GetBindString can return the referrer, BINDSTRING_XDR_ORIGIN, or the root URL, BINDSTRING_ROOTDOC_URL, but those require newer versions of IE and my legacy app must support older XP installs that might even have IE6 or IE7, so I'd rather not use these.
Tagged as TWebBrowser because that is actually what I'm using (Borland Builder 6 C++), but don't need answers specific to that platform.
As the Asynchronous Pluggable Protocol Handler us very low level, you cannot attach handlers individually to different rendering controls.
Here is a way to get the referrer:
Obtain BINDSTRING_HEADERS
Extract the referrer by parsing the line Referer: http://....
See also How can I add an extra http header using IHTTPNegotiate?
Here is another crazy way:
Create another Asynchronous Pluggable Protocol Handler by calling RegisterMimeFilter.
Monitor text/plain and text/html
Scan the incoming email source (content comes incrementally) and parse store all image links in a dictionary
In NameSpaceHandler you can use this dictionary to find the reference of any image resources.
currently the JSONStore API provides a load() method that says in the documentation:
This function always stores whatever it gets back from the adapter. If
the data exists, it is duplicated in the collection". This means that
if you want to avoid duplicates by calling load() on an already
populated collection, you need to empty or drop the collection before.
But if you want to be able to keep the elements you already have in
the collection in case there is no more connectivity and your
application goes for offline mode, you also need to keep track of
these existing elements.
Since the API doesn't provide a "overwrite" option that would replace the existing elements in case the call to the adapter succeeds, I'm wondering what kind of logic should be put in place in order to manage both offline availability of data and capability to refresh at any time? It is not that obvious to manage all the failure cases by nesting the JS code due to the promises...
Thanks for your advices!
One approach to achieve this:
Use enhance to create your own load method (i.e. loadAndOverwrite). You should have access to the all the variables kept inside an JSONStore instance (collection name, adapter name, adapter load procedure name, etc. -- you will probably use those variables in the invokeProcedure step below).
Call push to make sure there are no local changes.
Call invokeProcedure to get data, all the variables you need should be provided in the context of enhance.
Find if the document already exists and then remove it. Use {push: false} so JSONStore won't track that change.
Use add to add the new/updated document. Use {push: false} so JSONStore won't track that change.
Alternatively, if the document exists you can use replace to update it.
Alternatively, you can use removeCollection and call load again to refresh the data.
There's an example that shows how to use all those API calls here.
Regarding promises, read this from InfoCenter and this from HTML5Rocks. Google can provide more information.
I am working on a VB.NET batch PDF exporting program for CAD drawings. The programs runs fine, but the architecture is a mess. Basically, one big function takes the entire process from start to finish. I would like to make a separate class, or several, to do the exporting work.
Here's the problem:
Sometimes the pdf file which will be created by my program already exists. In this case, I would like to ask the user if he/she would like to overwrite existing PDFs. I only want to do this if there is actually something which will be overwritten and I only want to do this once. In other words, "yes" = "yes to all." It seems wrong to have the form (which will be calling this new PDF exporting class) figure out what the PDF files will be called and whether there will be any overwrites. In fact, it would be best to have the names for the PDF files determined as the individual CAD drawings are processed (because I might want to use information which will only become available after loading the files in the CAD program in the background).
Here's the question:
How should I handle the process of prompting the user? I would like to keep all GUI logic (even something as simple as a dialog box) out of my PDF exporting class. I need a way for the PDF exporting class to say, "Hey, I need to know if I should overwrite or skip this file," and the form class (or any other class) to say, "Um, ok, I'll ask the user and get back to you."
It seems there ought to be some pattern to handle this situation. What is it?
Follow-ups:
Events: It seems like this is a good way to go. Is this about what the code should look like in the PDF exporting class?
Dim e As New FileExistsEventArgs(PDFFile)
RaiseEvent FileExists(Me, e)
If e.Overwrite Then
'Do stuff here
End If
A crazy idea: What about passing delegate functions to the export method of the PDF exporting class to handle the overwrite case?
You could use an Event, create a custom event argument class with a property on it that the application can call. Then when your app is handling the event prompt the user and then tell the exporter what to do. I'm a c# guy so let me give you a sample in there first:
void form_Load(object sender,EventArgs e)
{
//We are subscribing to the event here. In VB this is done differently
pdfExporter.FileExists+=new FileExistsEventHandler(pdfExporter_fileExists)
}
void pdfExporter_fileExists(object sender, FileExistsEventArgs e)
{
//prompUser takes the file and asks the user
if (promptUser(e.FileName))
{
}
}
Your PDF making class should raise an event. This event should have an eventargs object, which can have a boolean property called "Overwrite" which the GUI sets in whatever fashion you want. When the event returns in your PDF class you'll have the user's decision and can overwrite or not as needed. The Gui can handle the event anyway it likes.
Also, I commend you for working to keep the two seperate!
So the appropriate method on your class needs an optional parameter of
[OverwriteExisting as Boolean = False]
However your form will need to handle the logic of establishing whether or not a file exists. It seems to me that this would not be a function that you would want encapsulated within your PDF export class anyway. Assuming that your form or other function/class ascertains that an overwrite is required then the export methos is called passing True as a Boolean to your export class.
You could do a two phase commit type of thing.
The class has two interfaces, one for prepping the filenames and filesystem, and another for doing the actual work.
So the first phase, the GUI calls the initialization interface, and gets a quick answer as to whether or not anything needs over-writing. Possibly even a comprehensive list of the files that will get over-written. User answers, the boolean variable in the other responses is known, and then the exporter gets to the real work, and the user can go do something else.
There would be some duplication of computation, but it's probably worth it to get the user's part of the operation over with as soon as possible.
You can't keep the GUI stuff out of the PDF Exporting Code. but you can precisely define the minimum needed and not be tied to whatever framework you are using.
How I do it is that I have a Status class, and a Progress class. The two exist because Status is design to update a status message, and the Progress Bar is designed to work with a indicator of progress.
Both of them work with a object that has a class type of IStatusDisplay and IPrograssDisplay respectfully.
My GUI defines a object implementing IStatusDisplay (or IProgressDisplay) and registers as the current display with the DLL having Status and Progress. The DLL with Status and Progress also have two singleton called NullStatus and NullProgress that can be used when there is no UI feedback wanted.
With this scheme I can pepper my code with as many Status or Progress updates I want and I only worry about the implementations at the GUI Layer. If I want a silent process I can just use the Null objects. Also if I completely change my GUI Framework all the new GUI has to do is make the new object that implements the IStatusDisplay, IProgressDisplay.
A alternative is to raise events but I find that confusing and complicated to handle at the GUI level. Especially if you have multiple screen the user could switch between. By using a Interface you make the connection clearer and more maintainable in the longe.
EDIT
You can create a Prompt Class and a IPromptDisplay to handle situation like asking whether you want to overwrite files.
For example
Dim P as New Prompt(MyPromptDisplay,PromptEnum.YesNo)
'MyPromptDisplay is of IPromptDisplay and was registered by the GUI when the application was initialized
If PromptYesNo.Ask("Do you wish to overwrite files")= PromptReply.Yes Then
'Do stuff here
End If
I am trying to establish the best practice for handling the creation of child objects when the parent object is incomplete or doesn't yet exist in a web application. I want to handle this in a stateless way so in memory objects are out.
For example, say we have a bug tracking application.
A Bug has a title and a description (both required) and any number of attachments. So the "Bug" is the parent object with a list of "Attachment" children.
So you present a page with a title input, a description input, and a file input to add an attachment. People then add the attachments but we haven't created the Parent Bug as yet.
How do you handle persisting the added attachments ?
Obviously we have to keep track of the attachments added, but at this point we haven't persisted the parent "Bug" object to attach the "Attachment" to.
Create the incomplete bug and define a process for handling incompleteness. (Wait X minutes/hours/days, then delete it/email someone/accept it as it is.) Even without a title or description, knowing that a problem occurred and the information in the attachment is potentially useful. The attachment may include a full description, but the user just put it somewhere other than you'd attended. Or it may only contain scattered data points which are meaningless on their own - but could corroborate another user's report.
I would normally just create the Bug object and its child, the Attachment object, within the same HTTP response after the user has submitted the form.
If I'm reading you right, the user input consists of a single form with the aforementioned fields for bug title, description, and the attached file. After the user fills out these fields (including the selection of a file to upload), then clicks on Submit, your application receives all three of these pieces of data simultaneously, as POST variables in the HTTP request. (The attachment is just another bit of POST data, as described in RFC 1867.)
From your application's end, depending on what kind of framework you are using, you will probably be given a filename pointing to the location of the uploaded file in some suitable temporary directory. E.g., with Perl's CGI module, you can do:
use CGI qw(:standard);
my $query = CGI->new;
print "Bug title: " . $query->param("title") . "\n";
print "Description: " . $query->param("description"). "\n";
print "Path to uploaded attachment: " . $query->param("attachment") . "\n";
to obtain the name of the uploaded file (the file data sent through the form by your user is automatically saved in a temporary file for your convenience), along with its metadata. Since you have access to both the textual field data and the file attachment simultaneously, you can create your Bug and Attachment objects in whatever order you please, without needing to persist any incomplete data across HTTP responses.
Or am I not understanding you here?
In this case I would consider storing the attachments in some type of temporary storage, be it Session State, a temp directory on the file system, or perhaps a database. Once the bug has been saved, I would then copy the attachments to their actual place.
Careful with session though, if you let them upload large attachments you could push memory issues depending on your environment.
One approach I saw before was as soon as the user opens the new bug form, a new bug is generated in your database. Depending on your app this may or may not be a good thing. If your collecting data from a user for example, this is useful as you get some intelligence even if they fail to enter the data, and leave your site. You still know they started the process, and whatever else you collected like user agent etc..