Hey all, i've been out of the umbraco scene for quite a while but now getting back into it and obviously now is all MVC based etc macro partial views and well you know!
Being honest i'm quite struggling to understand it all, i have a Umbraco 7 installation out of webmatrix, i'm trying to create a members area for the site and can't quite figure out how to create a simple form where members can create a new node in umbraco (For examples sake it's a 'deal') with just the nodename & a price textstring field.
I have the members resgistration etc all working from a macro partial view which also sets the members 'group' upon registration.
Could i have some guidance on how to go about this can it be done in just a macro partial view or does it need all this surface controllers etc?
I think my first mistake was not instaling umbraco via VS but hoping this just makes a nuisance and doesn't stop it dead!
Here is how you can create a node from a form in a Macro Partial, without going through a SurfaceController. (Very basic example, but i works and can probobly lead you in the right way.)
@inherits Umbraco.Web.Macros.PartialViewMacroPage
@{
if (HttpContext.Current.Request.HttpMethod == "POST")
{
var name = Request["name"];
var node = ApplicationContext.Current.Services.ContentService.CreateContent(name: name, parentId: 1053, contentTypeAlias: "page", userId: 0);
ApplicationContext.Current.Services.ContentService.SaveAndPublishWithStatus(node);
}
}
<form method="POST">
<input type="text" name="name"/>
<input type="submit" value="Create node">
</form>
Hey thanks for that, had just cracked it before i saw your post however think they work slightly different so unsure whats best, heres what i came up with.
@using umbraco.cms.businesslogic.web
@* Some global variables *@
@{
var successfulPost = false;
var name = Request["name"];
var message = Request["message"];
var parent = Request["parent"];
}
@* Handle form post: create a new document if a valid post*@
@if (IsPost)
{
if (name!="" && message !="" && parent !="")
{
var dt = DocumentType.GetByAlias("Deal");
@* Make sure its a valid document type alias *@
if (dt != null)
{
var author = umbraco.BusinessLogic.User.GetUser(0);
var doc = Document.MakeNew("Comment", dt, author, Convert.ToInt32(parent));
doc.getProperty("name").Value = parent;
doc.getProperty("mainText").Value = message;
@* Tell umbraco to publish the document *@
doc.Publish(author);
umbraco.library.UpdateDocumentCache(doc.Id);
successfulPost = true;
}
}
}
@* Render the Html *@
<hr/>
@if (successfulPost)
{
<h3>Successful post</h3>
<p>Thank you <strong>@name</strong> for your message:</p>
<p>@message</p>
}
<h3>Add a new comment:</h3>
<form method="post">
<fieldset>
<label for="name">Your name</label>
<input type="text" name="name" id="name"/><br/>
<label for="parent">Location</label>
<select name="parent" id="parent">
<option value="1079"></option>
<option value="1067">Spain</option>
</select><br/>
<label for="message">Comment</label>
<textarea name="message" id="message"></textarea><br/>
<input type="submit" value="Post comment"/>
</fieldset>
</form>
No they both work in the same way, but you are using the Obsolete way of creating a document. It works, but there is always a risk in using obsole methods since they could potensionally get removed in newer versions and lead to problem when you upgrade. I´d recomeend using the ContentService.
--
About your bonus question:
I think (note think) you cant (read should´nt) upload a file from your view since you are creating files on your server enviroment without going through a Controller post of some sort or calling the server from a Ajax request.
Here´s a link about Uploading files with MVC and Ajax. (Remeber to use a SurfaceController instead of a regular Controller):
Whilst you can create nodes, members etc. using a simple form in a Razor view, it is definitely recommended to move this kind of logic to a Surface Controller. They're not that scary, and will make your code a lot cleaner and more manageable.
Here's a simple article on how to create a login form using a Surface Controller - but the basic principle works for all types of forms where you want to submit some data, do something and then return back to a page.
Managed to crack both problems, membership all works great with my above code and also have a multiple image uploader that works frontend in the members section just using a partial view macro file
@using umbraco.cms.businesslogic.web
@using System.Web.Security
@* A Razor script to add a basic comment function to Umbraco pages
You need a document type called Comment with a textstring property
called commentName and a textbox multiple property called commentMessage
You also need to allow the Comment document type as child document type
to your textpage document type.
Create this script with a macro and add it below the bodyText in your
template(s) *@
@* Some global variables *@
@{
var successfulPost = false;
var name = Request["name"];
var message = Request["message"];
var parent = Request["parent"];
var price = Request["price"];
}
@* Handle form post: create a new document if a valid post*@
@if (IsPost)
{
if (name != "" && message != "" && parent != "")
{
var dt = DocumentType.GetByAlias("Deal");
@* Make sure its a valid document type alias *@
if (dt != null)
{
var author = umbraco.BusinessLogic.User.GetUser(0);
var member = Membership.GetUser();
var doc = Document.MakeNew(name, dt, author, Convert.ToInt32(parent));
doc.getProperty("name").Value = name;
doc.getProperty("mainText").Value = message;
doc.getProperty("price").Value = price;
doc.getProperty("client").Value = Convert.ToString(member);
var imageIds = "";
var mediaFiles = Request.Files;
if (ApplicationContext.Current != null && mediaFiles!=null && mediaFiles.Count>0)
{
var ms = ApplicationContext.Current.Services.MediaService;
for (int i = 0; i < mediaFiles.Count; i++)
{
HttpPostedFileBase mediaFile = mediaFiles[i];
if (mediaFile != null && mediaFile.ContentLength > 0)
{
var newFile = ms.CreateMedia(mediaFile.FileName, -1, "Image");
newFile.SetValue("umbracoFile", mediaFile);
ms.Save(newFile);
imageIds += newFile.Id + ",";
}
}
}
if (!string.IsNullOrEmpty(imageIds))
{
doc.getProperty("images").Value = imageIds.TrimEnd(',');
}
@* Tell umbraco to publish the document *@
doc.Publish(author);
umbraco.library.UpdateDocumentCache(doc.Id);
successfulPost = true;
}
}
}
@* Render the Html *@
<hr />
@if (successfulPost)
{
<h3>Successful post</h3>
<p>Thank you <strong>@name</strong> for your message:</p>
<p>@message</p>
}
<h3>Add a new Deal:</h3>
<form method="post" enctype = "multipart/form-data">
<fieldset>
<label for="name">Tagline</label><br />
<input type="text" name="name" id="name" /><br />
<label for="price">Deal Price</label><br />
<input type="text" name="price" id="price" /><br />
<label for="parent">Location</label><br />
<select name="parent" id="parent">
<option value="1065">Spain</option>
<option value="1117">Portugal</option>
<option value="1121">Italy</option>
</select><br />
<label for="message">Details</label><br />
<textarea name="message" id="message"></textarea><br />
<label for="price">Image</label><br />
<input type="file" name="image" id="image" multiple/><br />
<input type="submit" value="Post comment" />
</fieldset>
</form>
It's a good effort, but I would still definitely recommend moving the logic to a controller - it would be much cleaner.
And you really, really shouldn't be using deprecated services such as umbraco.BusinessLogic.User or Document.MakeNew - these are obsolete, perform poorly and are going to be removed totally in Umbraco 8.
To create a new page in Umbraco you should use the ContentService eg.
var contentService = UmbracoContext.Current.Application.Services.ContentService;
var parent = contentService.GetById(1234); // ID of the node you are going to create the content under
var newContent = contentService.CreateContent("Node Name", parent, "DocumentTypeAlias");
newContent.SetValue("name", "Your Name");
newContent.SetValue("mainText", "Your text");
// etc
var result = contentService.SaveAndPublishWithStatus(newContent);
if (result.Success)
{
// it worked
}
else
{
var exception = result.Exception; // check result for any errors
}
Create Nodes Programmaticaly
Hey all, i've been out of the umbraco scene for quite a while but now getting back into it and obviously now is all MVC based etc macro partial views and well you know!
Being honest i'm quite struggling to understand it all, i have a Umbraco 7 installation out of webmatrix, i'm trying to create a members area for the site and can't quite figure out how to create a simple form where members can create a new node in umbraco (For examples sake it's a 'deal') with just the nodename & a price textstring field.
I have the members resgistration etc all working from a macro partial view which also sets the members 'group' upon registration.
Could i have some guidance on how to go about this can it be done in just a macro partial view or does it need all this surface controllers etc?
I think my first mistake was not instaling umbraco via VS but hoping this just makes a nuisance and doesn't stop it dead!
Thanks all Pete
Hi Peter. Welcome back! :)
Here is how you can create a node from a form in a Macro Partial, without going through a SurfaceController. (Very basic example, but i works and can probobly lead you in the right way.)
Let me know if it works out for you!!
Hey thanks for that, had just cracked it before i saw your post however think they work slightly different so unsure whats best, heres what i came up with.
I do have another test for you though! Is it possible to have an image upload on the same form?
Great Peter!
No they both work in the same way, but you are using the Obsolete way of creating a document. It works, but there is always a risk in using obsole methods since they could potensionally get removed in newer versions and lead to problem when you upgrade. I´d recomeend using the ContentService.
--
About your bonus question:
I think (note think) you cant (read should´nt) upload a file from your view since you are creating files on your server enviroment without going through a Controller post of some sort or calling the server from a Ajax request.
Here´s a link about Uploading files with MVC and Ajax. (Remeber to use a SurfaceController instead of a regular Controller):
https://cmatskas.com/upload-files-in-asp-net-mvc-with-javascript-and-c/
Best of luck to you!! Hope i could be of any help to you!
Bonus tip.
If you are using Umbraco Forms, you could easily create this kind of form, then attaching a workflow that creates a node.
Whilst you can create nodes, members etc. using a simple form in a Razor view, it is definitely recommended to move this kind of logic to a Surface Controller. They're not that scary, and will make your code a lot cleaner and more manageable.
Here's a simple article on how to create a login form using a Surface Controller - but the basic principle works for all types of forms where you want to submit some data, do something and then return back to a page.
http://24days.in/umbraco/2012/creating-a-login-form-with-umbraco-mvc-surfacecontroller/
For membership, have a read of this article that tells you how to create members programmatically etc.
http://24days.in/umbraco/2015/membership-apis-investigation/
Managed to crack both problems, membership all works great with my above code and also have a multiple image uploader that works frontend in the members section just using a partial view macro file
Great job! :) #h5yr
It's a good effort, but I would still definitely recommend moving the logic to a controller - it would be much cleaner.
And you really, really shouldn't be using deprecated services such as umbraco.BusinessLogic.User or Document.MakeNew - these are obsolete, perform poorly and are going to be removed totally in Umbraco 8.
To create a new page in Umbraco you should use the ContentService eg.
All the services you need are documented here:
https://our.umbraco.org/documentation/Reference/Management/Services/
is working on a reply...