Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Peter Alcock 113 posts 176 karma points
    Apr 20, 2016 @ 05:40
    Peter Alcock
    0

    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

  • Dennis Adolfi 1082 posts 6446 karma points MVP 5x c-trib
    Apr 20, 2016 @ 06:35
    Dennis Adolfi
    0

    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.)

    @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>
    

    Let me know if it works out for you!!

  • Peter Alcock 113 posts 176 karma points
    Apr 20, 2016 @ 06:45
    Peter Alcock
    0

    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>
    
  • Peter Alcock 113 posts 176 karma points
    Apr 20, 2016 @ 06:46
    Peter Alcock
    0

    I do have another test for you though! Is it possible to have an image upload on the same form?

  • Dennis Adolfi 1082 posts 6446 karma points MVP 5x c-trib
    Apr 20, 2016 @ 07:00
    Dennis Adolfi
    0

    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!

  • Dennis Adolfi 1082 posts 6446 karma points MVP 5x c-trib
    Apr 20, 2016 @ 07:03
    Dennis Adolfi
    0

    Bonus tip.

    If you are using Umbraco Forms, you could easily create this kind of form, then attaching a workflow that creates a node.

  • Dan Diplo 1554 posts 6205 karma points MVP 5x c-trib
    Apr 20, 2016 @ 07:27
    Dan Diplo
    1

    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/

  • Peter Alcock 113 posts 176 karma points
    Apr 21, 2016 @ 10:46
    Peter Alcock
    1

    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>
    
  • Dennis Adolfi 1082 posts 6446 karma points MVP 5x c-trib
    Apr 21, 2016 @ 10:55
    Dennis Adolfi
    0

    Great job! :) #h5yr

  • Dan Diplo 1554 posts 6205 karma points MVP 5x c-trib
    Apr 21, 2016 @ 18:48
    Dan Diplo
    1

    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
        }
    

    All the services you need are documented here:

    https://our.umbraco.org/documentation/Reference/Management/Services/

Please Sign in or register to post replies

Write your reply to:

Draft